Materializers
Materializers are functions that allow you to write to your database in response to events. Materializers are executed in the order of the events in the eventlog.
Example
Section titled “Example”import { const defineMaterializer: <TEventDef extends State.SQLite.EventDef.AnyWithoutFn>(_eventDef: TEventDef, materializer: State.SQLite.Materializer<TEventDef>) => State.SQLite.Materializer<TEventDef>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer, import Events
Events, import Schema
Schema, import State
State } from '@livestore/livestore'
export const const todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos = import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}, Partial<...>>(args: { ...;} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotate({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "todos"
name: 'todos', columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}
columns: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: () => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text(), completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;}
completed: import State
State.import SQLite
SQLite.const boolean: <boolean, false, false, false, false>(args: { default?: false; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
boolean({ default?: false
default: false }), previousIds: { columnType: "text"; schema: Schema.Codec<readonly string[] | null, string | null, never, never>; default: Some<any> | None<never>; nullable: true; primaryKey: false; autoIncrement: false;}
previousIds: import State
State.import SQLite
SQLite.const json: <readonly string[], true, any, false, false>(args: { schema?: Schema.Codec<readonly string[], any, never, never>; default?: any; nullable?: true; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<readonly string[] | null, string | null, never, never>; default: Some<any> | None<never>; nullable: true; primaryKey: false; autoIncrement: false;} (+1 overload)
json({ schema?: Schema.Codec<readonly string[], any, never, never>
schema: import Schema
Schema.Array<Schema.String>(self: Schema.String): Schema.$Array<Schema.String>export Array
Defines a ReadonlyArray schema for a given element schema.
Example (Defining an array of strings)
import { Schema } from "effect"
const schema = Schema.Array(Schema.String)
const result = Schema.decodeUnknownSync(schema)(["a", "b", "c"])console.log(result)// [ 'a', 'b', 'c' ]
Array(import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String), nullable?: true
nullable: true, }), },})
export const const table1: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table1 = import State
State.import SQLite
SQLite.function table<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "settings"; columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; }; };} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotate({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "settings"
name: 'settings', columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false;}
someVal: import State
State.import SQLite
SQLite.const integer: <number, number, false, 0, false, false>(args: { schema?: Schema.Codec<number, number, never, never>; default?: 0; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
integer({ default?: 0
default: 0 }), },})
export const const table2: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table2 = import State
State.import SQLite
SQLite.function table<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "preferences"; columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; }; };} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotate({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "preferences"
name: 'preferences', columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false;}
otherVal: import State
State.import SQLite
SQLite.const text: <string, string, false, "default", false, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: "default"; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text({ default?: "default"
default: 'default' }), },})
export const const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events = { todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>
todoCreated: import Events
Events.synced<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>(args: { name: "todoCreated"; schema: Schema.Codec<{ readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "todoCreated"
name: 'todoCreated', schema: Schema.Codec<{ readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}>(fields: { readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, completed: Schema.optional<Schema.Boolean>
completed: import Schema
Schema.const Boolean: Schema.Boolean
Type-level representation of
Boolean
.
Schema for boolean values. Validates that the input is typeof "boolean".
When to use
Use to validate values that are already JavaScript booleans.
Boolean.Pipeable.pipe<Schema.Boolean, Schema.optional<Schema.Boolean>>(this: Schema.Boolean, ab: (_: Schema.Boolean) => Schema.optional<Schema.Boolean>): Schema.optional<Schema.Boolean> (+21 overloads)
pipe(import Schema
Schema.const optional: optionalLambda
Type-level representation returned by
optional
.
Marks a struct field as optional, allowing the key to be absent or
undefined.
Details
The resulting property may be absent or explicitly set to undefined.
Equivalent to optionalKey(UndefinedOr(S)).
Use
optionalKey
instead if you want exact optional semantics (absent
only, not undefined).
Example (Defining an optional field accepting undefined)
import { Schema } from "effect"
const schema = Schema.Struct({ name: Schema.String, age: Schema.optional(Schema.Number)})
// { readonly name: string; readonly age?: number | undefined }type Person = typeof schema.Type
optional), }), }), userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>
userPreferencesUpdated: import Events
Events.synced<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>(args: { name: "userPreferencesUpdated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">, never, never>;} & Omit<...>): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "userPreferencesUpdated"
name: 'userPreferencesUpdated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly userId: Schema.String; readonly theme: Schema.String;}>(fields: { readonly userId: Schema.String; readonly theme: Schema.String;}): Schema.Struct<{ readonly userId: Schema.String; readonly theme: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ userId: Schema.String
userId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, theme: Schema.String
theme: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), factoryResetApplied: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>
factoryResetApplied: import Events
Events.synced<"factoryResetApplied", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>(args: { name: "factoryResetApplied"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{}, "Type">, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<...>>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "factoryResetApplied"
name: 'factoryResetApplied', schema: Schema.Codec<Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{}>(fields: {}): Schema.Struct<{}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({}), }),} as type const = { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
const
export const const materializers: { todoCreated: State.SQLite.Materializer<State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>>; userPreferencesUpdated: State.SQLite.Materializer<State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>>; factoryResetApplied: State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}>(_eventDefRecord: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events, { [const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>
todoCreated.name: "todoCreated"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>>(_eventDef: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>
todoCreated, ({ id: string
id, text: string
text, completed: boolean | undefined
completed }) => const todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos.insert: (values: { readonly text: string; readonly id: string; readonly completed?: boolean; readonly previousIds?: readonly string[] | null;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly previousIds: Schema.Codec<readonly string[] | null, string | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { ...;}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ id: string
id, text: string
text, completed?: boolean
completed: completed: boolean | undefined
completed ?? false }), ), [const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>
userPreferencesUpdated.name: "userPreferencesUpdated"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>>(_eventDef: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>, materializer: State.SQLite.Materializer<...>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>
userPreferencesUpdated, ({ userId: string
userId, theme: string
theme }) => { var console: Console
console.Console.log(...data: any[]): void (+2 overloads)
The console.log() static method outputs a message to the console.
log(`User ${userId: string
userId} updated theme to ${theme: string
theme}.`) return [] }), [const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.factoryResetApplied: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>
factoryResetApplied.name: "factoryResetApplied"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"factoryResetApplied", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>>(_eventDef: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.factoryResetApplied: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>
factoryResetApplied, () => [ const table1: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table1.update: (values: Partial<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly someVal: Schema.Codec<number, number, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly someVal: Schema.Codec<number, number, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<...>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ someVal?: number
someVal: 0 }), const table2: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table2.update: (values: Partial<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly otherVal: Schema.Codec<string, string, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly otherVal: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<...>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ otherVal?: string
otherVal: 'default' }), // Raw SQL is also supported via { sql, bindValues } { sql: string
sql: 'DELETE FROM todos', bindValues: BindValues
bindValues: {} }, ]),})Reading from the database in materializers
Section titled “Reading from the database in materializers”Sometimes it can be useful to query your current state when executing a materializer. This can be done by using ctx.query in your materializer function.
import { const defineMaterializer: <TEventDef extends State.SQLite.EventDef.AnyWithoutFn>(_eventDef: TEventDef, materializer: State.SQLite.Materializer<TEventDef>) => State.SQLite.Materializer<TEventDef>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer, import Events
Events, import Schema
Schema, import State
State } from '@livestore/livestore'
import { import todos
todos } from './example.ts'
const const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>;}
events = { todoCreated: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}>
todoCreated: import Events
Events.synced<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}>(args: { name: "todoCreated"; schema: Schema.Codec<{ readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "todoCreated"
name: 'todoCreated', schema: Schema.Codec<{ readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}>(fields: { readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, completed: Schema.optional<Schema.Boolean>
completed: import Schema
Schema.const Boolean: Schema.Boolean
Type-level representation of
Boolean
.
Schema for boolean values. Validates that the input is typeof "boolean".
When to use
Use to validate values that are already JavaScript booleans.
Boolean.Pipeable.pipe<Schema.Boolean, Schema.optional<Schema.Boolean>>(this: Schema.Boolean, ab: (_: Schema.Boolean) => Schema.optional<Schema.Boolean>): Schema.optional<Schema.Boolean> (+21 overloads)
pipe(import Schema
Schema.const optional: optionalLambda
Type-level representation returned by
optional
.
Marks a struct field as optional, allowing the key to be absent or
undefined.
Details
The resulting property may be absent or explicitly set to undefined.
Equivalent to optionalKey(UndefinedOr(S)).
Use
optionalKey
instead if you want exact optional semantics (absent
only, not undefined).
Example (Defining an optional field accepting undefined)
import { Schema } from "effect"
const schema = Schema.Struct({ name: Schema.String, age: Schema.optional(Schema.Number)})
// { readonly name: string; readonly age?: number | undefined }type Person = typeof schema.Type
optional), }), }),} as type const = { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>;}
const
export const const materializers: { todoCreated: State.SQLite.Materializer<State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>;}>(_eventDefRecord: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>;}, handlers: { todoCreated: State.SQLite.Materializer<State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>>;}) => { todoCreated: State.SQLite.Materializer<State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>>;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>;}
events, { [const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>;}
events.todoCreated: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}>
todoCreated.name: "todoCreated"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}>>(_eventDef: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}>>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>;}
events.todoCreated: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined;}>
todoCreated, ({ id: string
id, text: string
text, completed: boolean | undefined
completed }, ctx: { currentFacts: State.SQLite.EventDefFacts; eventDef: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>; query: State.SQLite.MaterializerContextQuery; event: Decoded;}
ctx) => { const const previousIds: readonly unknown[]
previousIds = ctx: { currentFacts: State.SQLite.EventDefFacts; eventDef: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>; query: State.SQLite.MaterializerContextQuery; event: Decoded;}
ctx.query: (args: { query: string; bindValues: ParamsObject;}) => ReadonlyArray<unknown> (+1 overload)
Query with raw SQL and bind values.
query(import todos
todos.any
select('id')) // ctx.query also supports raw SQL via { query, bindValues } const const existingTodos: readonly unknown[]
existingTodos = ctx: { currentFacts: State.SQLite.EventDefFacts; eventDef: State.SQLite.EventDef<"todoCreated", { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }, { readonly id: string; readonly text: string; readonly completed?: boolean | undefined; }>; query: State.SQLite.MaterializerContextQuery; event: Decoded;}
ctx.query: (args: { query: string; bindValues: ParamsObject;}) => ReadonlyArray<unknown> (+1 overload)
Query with raw SQL and bind values.
query({ query: string
query: 'SELECT id FROM todos', bindValues: ParamsObject
bindValues: {} }) return import todos
todos.any
insert({ id: string
id: `${const existingTodos: readonly unknown[]
existingTodos.ReadonlyArray<unknown>.length: number
Gets the length of the array. This is a number one higher than the highest element defined in an array.
length}-${id: string
id}`, text: string
text, completed: boolean
completed: completed: boolean | undefined
completed ?? false, previousIds: readonly unknown[]
previousIds }) }),})import { const defineMaterializer: <TEventDef extends State.SQLite.EventDef.AnyWithoutFn>(_eventDef: TEventDef, materializer: State.SQLite.Materializer<TEventDef>) => State.SQLite.Materializer<TEventDef>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer, import Events
Events, import Schema
Schema, import State
State } from '@livestore/livestore'
export const const todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos = import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}, Partial<...>>(args: { ...;} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotate({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "todos"
name: 'todos', columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}
columns: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: () => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text(), completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;}
completed: import State
State.import SQLite
SQLite.const boolean: <boolean, false, false, false, false>(args: { default?: false; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
boolean({ default?: false
default: false }), previousIds: { columnType: "text"; schema: Schema.Codec<readonly string[] | null, string | null, never, never>; default: Some<any> | None<never>; nullable: true; primaryKey: false; autoIncrement: false;}
previousIds: import State
State.import SQLite
SQLite.const json: <readonly string[], true, any, false, false>(args: { schema?: Schema.Codec<readonly string[], any, never, never>; default?: any; nullable?: true; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<readonly string[] | null, string | null, never, never>; default: Some<any> | None<never>; nullable: true; primaryKey: false; autoIncrement: false;} (+1 overload)
json({ schema?: Schema.Codec<readonly string[], any, never, never>
schema: import Schema
Schema.Array<Schema.String>(self: Schema.String): Schema.$Array<Schema.String>export Array
Defines a ReadonlyArray schema for a given element schema.
Example (Defining an array of strings)
import { Schema } from "effect"
const schema = Schema.Array(Schema.String)
const result = Schema.decodeUnknownSync(schema)(["a", "b", "c"])console.log(result)// [ 'a', 'b', 'c' ]
Array(import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String), nullable?: true
nullable: true, }), },})
export const const table1: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table1 = import State
State.import SQLite
SQLite.function table<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "settings"; columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; }; };} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotate({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "settings"
name: 'settings', columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false;}
someVal: import State
State.import SQLite
SQLite.const integer: <number, number, false, 0, false, false>(args: { schema?: Schema.Codec<number, number, never, never>; default?: 0; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
integer({ default?: 0
default: 0 }), },})
export const const table2: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table2 = import State
State.import SQLite
SQLite.function table<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "preferences"; columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; }; };} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotate({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "preferences"
name: 'preferences', columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false;}
otherVal: import State
State.import SQLite
SQLite.const text: <string, string, false, "default", false, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: "default"; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text({ default?: "default"
default: 'default' }), },})
export const const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events = { todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>
todoCreated: import Events
Events.synced<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>(args: { name: "todoCreated"; schema: Schema.Codec<{ readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "todoCreated"
name: 'todoCreated', schema: Schema.Codec<{ readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}>(fields: { readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, completed: Schema.optional<Schema.Boolean>
completed: import Schema
Schema.const Boolean: Schema.Boolean
Type-level representation of
Boolean
.
Schema for boolean values. Validates that the input is typeof "boolean".
When to use
Use to validate values that are already JavaScript booleans.
Boolean.Pipeable.pipe<Schema.Boolean, Schema.optional<Schema.Boolean>>(this: Schema.Boolean, ab: (_: Schema.Boolean) => Schema.optional<Schema.Boolean>): Schema.optional<Schema.Boolean> (+21 overloads)
pipe(import Schema
Schema.const optional: optionalLambda
Type-level representation returned by
optional
.
Marks a struct field as optional, allowing the key to be absent or
undefined.
Details
The resulting property may be absent or explicitly set to undefined.
Equivalent to optionalKey(UndefinedOr(S)).
Use
optionalKey
instead if you want exact optional semantics (absent
only, not undefined).
Example (Defining an optional field accepting undefined)
import { Schema } from "effect"
const schema = Schema.Struct({ name: Schema.String, age: Schema.optional(Schema.Number)})
// { readonly name: string; readonly age?: number | undefined }type Person = typeof schema.Type
optional), }), }), userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>
userPreferencesUpdated: import Events
Events.synced<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>(args: { name: "userPreferencesUpdated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">, never, never>;} & Omit<...>): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "userPreferencesUpdated"
name: 'userPreferencesUpdated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly userId: Schema.String; readonly theme: Schema.String;}>(fields: { readonly userId: Schema.String; readonly theme: Schema.String;}): Schema.Struct<{ readonly userId: Schema.String; readonly theme: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ userId: Schema.String
userId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, theme: Schema.String
theme: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), factoryResetApplied: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>
factoryResetApplied: import Events
Events.synced<"factoryResetApplied", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>(args: { name: "factoryResetApplied"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{}, "Type">, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<...>>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "factoryResetApplied"
name: 'factoryResetApplied', schema: Schema.Codec<Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{}>(fields: {}): Schema.Struct<{}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({}), }),} as type const = { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
const
export const const materializers: { todoCreated: State.SQLite.Materializer<State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>>; userPreferencesUpdated: State.SQLite.Materializer<State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>>; factoryResetApplied: State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}>(_eventDefRecord: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events, { [const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>
todoCreated.name: "todoCreated"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>>(_eventDef: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>
todoCreated, ({ id: string
id, text: string
text, completed: boolean | undefined
completed }) => const todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos.insert: (values: { readonly text: string; readonly id: string; readonly completed?: boolean; readonly previousIds?: readonly string[] | null;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly previousIds: Schema.Codec<readonly string[] | null, string | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { ...;}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ id: string
id, text: string
text, completed?: boolean
completed: completed: boolean | undefined
completed ?? false }), ), [const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>
userPreferencesUpdated.name: "userPreferencesUpdated"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>>(_eventDef: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>, materializer: State.SQLite.Materializer<...>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>
userPreferencesUpdated, ({ userId: string
userId, theme: string
theme }) => { var console: Console
console.Console.log(...data: any[]): void (+2 overloads)
The console.log() static method outputs a message to the console.
log(`User ${userId: string
userId} updated theme to ${theme: string
theme}.`) return [] }), [const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.factoryResetApplied: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>
factoryResetApplied.name: "factoryResetApplied"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"factoryResetApplied", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>>(_eventDef: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.factoryResetApplied: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>
factoryResetApplied, () => [ const table1: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table1.update: (values: Partial<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly someVal: Schema.Codec<number, number, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly someVal: Schema.Codec<number, number, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<...>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ someVal?: number
someVal: 0 }), const table2: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table2.update: (values: Partial<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly otherVal: Schema.Codec<string, string, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly otherVal: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<...>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ otherVal?: string
otherVal: 'default' }), // Raw SQL is also supported via { sql, bindValues } { sql: string
sql: 'DELETE FROM todos', bindValues: BindValues
bindValues: {} }, ]),})Transactional behaviour
Section titled “Transactional behaviour”A materializer is always executed in a transaction. This transaction applies to:
- All database write operations returned by the materializer.
- Any
ctx.querycalls made within the materializer, ensuring a consistent view of the data.
Materializers can return:
- A single database write operation.
- An array of database write operations.
void(i.e., no return value) if no database modifications are needed.- An
Effectthat resolves to one of the above (e.g.,Effect.succeed(writeOp)orEffect.void).
The context object passed to each materializer provides query for database reads and event for the full event details.
Error handling
Section titled “Error handling”If a materializer function throws an error, or if an Effect returned by a materializer fails, the entire transaction for that event will be rolled back. This means any database changes attempted by that materializer for the failing event will not be persisted. The error will be logged, and the system will typically halt or flag the event as problematic, depending on the specific LiveStore setup.
If the error happens on the client which tries to commit the event, the event will never be committed and pushed to the sync backend.
In the future there will be ways to configure the error-handling behaviour, e.g. to allow skipping an incoming event when a materializer fails in order to avoid the app getting stuck. However, skipping events might also lead to diverging state across clients and should be used with caution.
Best practices
Section titled “Best practices”Side-effect free / deterministic
Section titled “Side-effect free / deterministic”It’s strongly recommended to make sure your materializers are side-effect free and deterministic. This also implies passing in all necessary data via the event payload.
Example:
import { function randomUUID(options?: RandomUUIDOptions): UUID
Generates a random RFC 4122 version 4 UUID. The UUID is generated using a
cryptographic pseudorandom number generator.
randomUUID } from 'node:crypto'
import { const defineMaterializer: <TEventDef extends State.SQLite.EventDef.AnyWithoutFn>(_eventDef: TEventDef, materializer: State.SQLite.Materializer<TEventDef>) => State.SQLite.Materializer<TEventDef>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer, import Events
Events, function nanoid(size?: number): string
Generate secure URL-friendly unique ID.
By default, the ID will have 21 symbols to have a collision probability
similar to UUID v4.
import { nanoid } from 'nanoid'model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
nanoid, import Schema
Schema, import State
State, type class Store<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}>
Central interface to a LiveStore database providing reactive queries, event commits, and sync.
A Store instance wraps a local SQLite database that is kept in sync with other clients via
an event log. Instead of mutating state directly, you commit events that get materialized
into database rows. Queries automatically re-run when their underlying tables change.
Creating a Store
Use createStore (Effect-based) or createStorePromise to obtain a Store instance.
In React applications, use StoreRegistry with <StoreRegistryProvider> and the useStore() hook
which manages the Store lifecycle.
Querying Data
Use
Store.query
for one-shot reads or
Store.subscribe
for reactive subscriptions.
Both accept query builders (e.g. tables.todo.where({ complete: true })) or custom LiveQueryDefs.
Committing Events
Use
Store.commit
to persist events. Events are immediately materialized locally and
asynchronously synced to other clients. Multiple events can be committed atomically.
Lifecycle
The Store must be shut down when no longer needed via
Store.shutdown
or
Store.shutdownPromise
. Framework integrations (React, Effect) handle this automatically.
Store } from '@livestore/livestore'
import { import todos
todos } from './example.ts'
declare const const store: Store<LiveStoreSchema.Any, {}>
store: class Store<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}>
Central interface to a LiveStore database providing reactive queries, event commits, and sync.
A Store instance wraps a local SQLite database that is kept in sync with other clients via
an event log. Instead of mutating state directly, you commit events that get materialized
into database rows. Queries automatically re-run when their underlying tables change.
Creating a Store
Use createStore (Effect-based) or createStorePromise to obtain a Store instance.
In React applications, use StoreRegistry with <StoreRegistryProvider> and the useStore() hook
which manages the Store lifecycle.
Querying Data
Use
Store.query
for one-shot reads or
Store.subscribe
for reactive subscriptions.
Both accept query builders (e.g. tables.todo.where({ complete: true })) or custom LiveQueryDefs.
Committing Events
Use
Store.commit
to persist events. Events are immediately materialized locally and
asynchronously synced to other clients. Multiple events can be committed atomically.
Lifecycle
The Store must be shut down when no longer needed via
Store.shutdown
or
Store.shutdownPromise
. Framework integrations (React, Effect) handle this automatically.
Store
export const const nondeterministicEvents: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Encoded">>;}
nondeterministicEvents = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Encoded">>
todoCreated: import Events
Events.synced<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Encoded">>(args: { name: "v1.TodoCreated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Type">, false>, "derived" | "clientOnly">): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly text: Schema.String;}>(fields: { readonly text: Schema.String;}): Schema.Struct<{ readonly text: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }),} as type const = { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Encoded">>;}
const
export const const nondeterministicMaterializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Encoded">>>;}
nondeterministicMaterializers = import State
State.import SQLite
SQLite.const materializers: <{ readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Encoded">>;}>(_eventDefRecord: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Encoded">>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const nondeterministicEvents: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Encoded">>;}
nondeterministicEvents, { [const nondeterministicEvents: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Encoded">>;}
nondeterministicEvents.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Encoded">>
todoCreated.name: "v1.TodoCreated"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Encoded">>>(_eventDef: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Encoded">>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<...>, Schema.Struct.ReadonlySide<...>>>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const nondeterministicEvents: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Encoded">>;}
nondeterministicEvents.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String;}, "Encoded">>
todoCreated, ({ text: string
text }) => import todos
todos.any
insert({ id: `${string}-${string}-${string}-${string}-${string}`
id: function randomUUID(options?: RandomUUIDOptions): UUID
Generates a random RFC 4122 version 4 UUID. The UUID is generated using a
cryptographic pseudorandom number generator.
randomUUID(), text: string
text }), ),})
const store: Store<LiveStoreSchema.Any, {}>
store.Store<LiveStoreSchema<TDbSchema extends DbSchema = DbSchema, TEventsDefRecord extends EventDefRecord = EventDefRecord>.Any, {}>.commit: <readonly [{ name: "v1.TodoCreated"; args: Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly text: Schema.String; }, "Type">;}]>(list_0: { name: "v1.TodoCreated"; args: Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly text: Schema.String; }, "Type">;}) => void (+3 overloads)
commit(const nondeterministicEvents: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Encoded">>;}
nondeterministicEvents.todoCreated: (args: Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly text: Schema.String;}, "Type">) => { name: "v1.TodoCreated"; args: Schema.Struct.ReadonlySide<{ readonly text: Schema.String; }, "Type">;}
Callable signature - creates a partial event with decoded arguments.
The returned object can be passed directly to store.commit().
todoCreated({ text: string
text: 'Buy groceries' }))
export const const deterministicEvents: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>;}
deterministicEvents = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoCreated: import Events
Events.synced<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">>(args: { name: "v1.TodoCreated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">, never, never>;} & Omit<...>): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>(fields: { readonly id: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }),} as type const = { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>;}
const
export const const deterministicMaterializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>>;}
deterministicMaterializers = import State
State.import SQLite
SQLite.const materializers: <{ readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>;}>(_eventDefRecord: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const deterministicEvents: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>;}
deterministicEvents, { [const deterministicEvents: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>;}
deterministicEvents.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoCreated.name: "v1.TodoCreated"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">>>(_eventDef: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">>, materializer: State.SQLite.Materializer<...>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const deterministicEvents: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>;}
deterministicEvents.todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoCreated, ({ id: string
id, text: string
text }) => import todos
todos.any
insert({ id: string
id, text: string
text }), ),})
const store: Store<LiveStoreSchema.Any, {}>
store.Store<LiveStoreSchema<TDbSchema extends DbSchema = DbSchema, TEventsDefRecord extends EventDefRecord = EventDefRecord>.Any, {}>.commit: <readonly [{ name: "v1.TodoCreated"; args: Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">;}]>(list_0: { name: "v1.TodoCreated"; args: Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">;}) => void (+3 overloads)
commit(const deterministicEvents: { readonly todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>;}
deterministicEvents.todoCreated: (args: Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">) => { name: "v1.TodoCreated"; args: Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">;}
Callable signature - creates a partial event with decoded arguments.
The returned object can be passed directly to store.commit().
todoCreated({ id: string
id: function nanoid(size?: number): string
Generate secure URL-friendly unique ID.
By default, the ID will have 21 symbols to have a collision probability
similar to UUID v4.
import { nanoid } from 'nanoid'model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
nanoid(), text: string
text: 'Buy groceries' }))import { const defineMaterializer: <TEventDef extends State.SQLite.EventDef.AnyWithoutFn>(_eventDef: TEventDef, materializer: State.SQLite.Materializer<TEventDef>) => State.SQLite.Materializer<TEventDef>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer, import Events
Events, import Schema
Schema, import State
State } from '@livestore/livestore'
export const const todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos = import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}, Partial<...>>(args: { ...;} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotate({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "todos"
name: 'todos', columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}
columns: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: () => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text(), completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;}
completed: import State
State.import SQLite
SQLite.const boolean: <boolean, false, false, false, false>(args: { default?: false; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
boolean({ default?: false
default: false }), previousIds: { columnType: "text"; schema: Schema.Codec<readonly string[] | null, string | null, never, never>; default: Some<any> | None<never>; nullable: true; primaryKey: false; autoIncrement: false;}
previousIds: import State
State.import SQLite
SQLite.const json: <readonly string[], true, any, false, false>(args: { schema?: Schema.Codec<readonly string[], any, never, never>; default?: any; nullable?: true; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<readonly string[] | null, string | null, never, never>; default: Some<any> | None<never>; nullable: true; primaryKey: false; autoIncrement: false;} (+1 overload)
json({ schema?: Schema.Codec<readonly string[], any, never, never>
schema: import Schema
Schema.Array<Schema.String>(self: Schema.String): Schema.$Array<Schema.String>export Array
Defines a ReadonlyArray schema for a given element schema.
Example (Defining an array of strings)
import { Schema } from "effect"
const schema = Schema.Array(Schema.String)
const result = Schema.decodeUnknownSync(schema)(["a", "b", "c"])console.log(result)// [ 'a', 'b', 'c' ]
Array(import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String), nullable?: true
nullable: true, }), },})
export const const table1: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table1 = import State
State.import SQLite
SQLite.function table<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "settings"; columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; }; };} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotate({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "settings"
name: 'settings', columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false;}
someVal: import State
State.import SQLite
SQLite.const integer: <number, number, false, 0, false, false>(args: { schema?: Schema.Codec<number, number, never, never>; default?: 0; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
integer({ default?: 0
default: 0 }), },})
export const const table2: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table2 = import State
State.import SQLite
SQLite.function table<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "preferences"; columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; }; };} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotate({ title: 'users' })const usersTable2 = State.SQLite.table({ schema: AnnotatedUserSchema,})
// Adding indexesconst PostSchema = Schema.Struct({ id: Schema.String.pipe(State.SQLite.withPrimaryKey), title: Schema.String, authorId: Schema.String, createdAt: Schema.Date,}).annotate({ identifier: 'posts' })
const postsTable = State.SQLite.table({ schema: PostSchema, indexes: [ { name: 'idx_posts_author', columns: ['authorId'] }, { name: 'idx_posts_created', columns: ['createdAt'], isUnique: false }, ],})
table({ name: "preferences"
name: 'preferences', columns: { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false;}
otherVal: import State
State.import SQLite
SQLite.const text: <string, string, false, "default", false, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: "default"; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text({ default?: "default"
default: 'default' }), },})
export const const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events = { todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>
todoCreated: import Events
Events.synced<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>(args: { name: "todoCreated"; schema: Schema.Codec<{ readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "todoCreated"
name: 'todoCreated', schema: Schema.Codec<{ readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}>(fields: { readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String; readonly completed: Schema.optional<Schema.Boolean>;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, completed: Schema.optional<Schema.Boolean>
completed: import Schema
Schema.const Boolean: Schema.Boolean
Type-level representation of
Boolean
.
Schema for boolean values. Validates that the input is typeof "boolean".
When to use
Use to validate values that are already JavaScript booleans.
Boolean.Pipeable.pipe<Schema.Boolean, Schema.optional<Schema.Boolean>>(this: Schema.Boolean, ab: (_: Schema.Boolean) => Schema.optional<Schema.Boolean>): Schema.optional<Schema.Boolean> (+21 overloads)
pipe(import Schema
Schema.const optional: optionalLambda
Type-level representation returned by
optional
.
Marks a struct field as optional, allowing the key to be absent or
undefined.
Details
The resulting property may be absent or explicitly set to undefined.
Equivalent to optionalKey(UndefinedOr(S)).
Use
optionalKey
instead if you want exact optional semantics (absent
only, not undefined).
Example (Defining an optional field accepting undefined)
import { Schema } from "effect"
const schema = Schema.Struct({ name: Schema.String, age: Schema.optional(Schema.Number)})
// { readonly name: string; readonly age?: number | undefined }type Person = typeof schema.Type
optional), }), }), userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>
userPreferencesUpdated: import Events
Events.synced<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>(args: { name: "userPreferencesUpdated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">, never, never>;} & Omit<...>): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "userPreferencesUpdated"
name: 'userPreferencesUpdated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly userId: Schema.String; readonly theme: Schema.String;}>(fields: { readonly userId: Schema.String; readonly theme: Schema.String;}): Schema.Struct<{ readonly userId: Schema.String; readonly theme: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ userId: Schema.String
userId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, theme: Schema.String
theme: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), factoryResetApplied: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>
factoryResetApplied: import Events
Events.synced<"factoryResetApplied", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>(args: { name: "factoryResetApplied"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{}, "Type">, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<...>>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "factoryResetApplied"
name: 'factoryResetApplied', schema: Schema.Codec<Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{}>(fields: {}): Schema.Struct<{}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({}), }),} as type const = { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
const
export const const materializers: { todoCreated: State.SQLite.Materializer<State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>>; userPreferencesUpdated: State.SQLite.Materializer<State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>>; factoryResetApplied: State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}>(_eventDefRecord: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events, { [const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>
todoCreated.name: "todoCreated"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>>(_eventDef: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined;}>
todoCreated, ({ id: string
id, text: string
text, completed: boolean | undefined
completed }) => const todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Codec<boolean, number, never, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly previousIds: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos.insert: (values: { readonly text: string; readonly id: string; readonly completed?: boolean; readonly previousIds?: readonly string[] | null;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly previousIds: Schema.Codec<readonly string[] | null, string | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { ...;}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ id: string
id, text: string
text, completed?: boolean
completed: completed: boolean | undefined
completed ?? false }), ), [const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>
userPreferencesUpdated.name: "userPreferencesUpdated"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>>(_eventDef: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>, materializer: State.SQLite.Materializer<...>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String;}, "Encoded">>
userPreferencesUpdated, ({ userId: string
userId, theme: string
theme }) => { var console: Console
console.Console.log(...data: any[]): void (+2 overloads)
The console.log() static method outputs a message to the console.
log(`User ${userId: string
userId} updated theme to ${theme: string
theme}.`) return [] }), [const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.factoryResetApplied: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>
factoryResetApplied.name: "factoryResetApplied"
Unique identifier for this event type. Conventionally versioned (e.g., v1.TodoCreated).
name]: defineMaterializer<State.SQLite.EventDef<"factoryResetApplied", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>>(_eventDef: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>, materializer: State.SQLite.Materializer<State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>>): State.SQLite.Materializer<...>
Type-safe wrapper for defining a single materializer.
Useful when defining materializers separately from the materializers() builder.
The first argument provides type inference for the second.
defineMaterializer(const events: { readonly todoCreated: State.SQLite.EventDef<"todoCreated", { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }, { readonly text: string; readonly id: string; readonly completed?: boolean | undefined; }>; readonly userPreferencesUpdated: State.SQLite.EventDef<"userPreferencesUpdated", Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly userId: Schema.String; readonly theme: Schema.String; }, "Encoded">>; readonly factoryResetApplied: State.SQLite.EventDef<...>;}
events.factoryResetApplied: State.SQLite.EventDef<"factoryResetApplied", Schema.Struct.ReadonlySide<{}, "Type">, Schema.Struct.ReadonlySide<{}, "Encoded">>
factoryResetApplied, () => [ const table1: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { columnType: "integer"; schema: Schema.Codec<number, number, never, never>; default: Some<0>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table1.update: (values: Partial<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly someVal: Schema.Codec<number, number, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly someVal: Schema.Codec<number, number, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"settings", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<...>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly someVal: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ someVal?: number
someVal: 0 }), const table2: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"default">; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
table2.update: (values: Partial<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly otherVal: Schema.Codec<string, string, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly otherVal: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"preferences", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<...>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly otherVal: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ otherVal?: string
otherVal: 'default' }), // Raw SQL is also supported via { sql, bindValues } { sql: string
sql: 'DELETE FROM todos', bindValues: BindValues
bindValues: {} }, ]),})