Todo app with shared workspaces
Let’s consider a fairly common application scenario: An app (in this case a todo app) with shared workspaces. For the sake of this guide, we’ll keep things simple but you should be able to nicely extend this to a more complex app.
Requirements
Section titled “Requirements”- There are multiple independent todo workspaces
- Each workspace is initially created by a single user
- Users can join the workspace by knowing the workspace id and get read and write access
- For simplicity, the user identity is chosen when the app initially starts (i.e. a username) but in a real app this would be handled by a proper auth setup
Data model
Section titled “Data model”- We are splitting up our data model into two kinds of stores (with respective eventlogs and SQLite databases): The
workspacestore and theuserstore.
workspace store (one per workspace)
Section titled “workspace store (one per workspace)”For the workspace store we have the following events:
workspaceCreatedtodoAddedtodoCompletedtodoDeleteduserJoined
And the following state model:
workspacetable (with a single row for the workspace itself)todotable (with one row per todo item)membertable (with one row per user who has joined the workspace)
user store (one per user)
Section titled “user store (one per user)”For the user store we have the following events:
workspaceCreatedworkspaceJoined
And the following state model:
usertable (with a single row for the user itself)
Note that the workspaceCreated event is used both in the workspace and the user store. This is because each eventlog should be “self-sufficient” and not rely on other eventlogs to be present to fulfill its purpose.
Schemas
Section titled “Schemas”User store:
import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, import State
State } from '@livestore/livestore'
// Emitted when this user creates a new workspaceconst const workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceCreated = import Events
Events.synced<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>(args: { name: "v1.WorkspaceCreated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: 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.WorkspaceCreated"
name: 'v1.WorkspaceCreated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}>(fields: { readonly workspaceId: Schema.String; readonly name: Schema.String;}): Schema.Struct<{ readonly workspaceId: Schema.String; readonly name: 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({ workspaceId: Schema.String
workspaceId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, name: Schema.String
name: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
// Emitted when this user joins an existing workspaceconst const workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceJoined = import Events
Events.synced<"v1.WorkspaceJoined", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>(args: { name: "v1.WorkspaceJoined"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: 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.WorkspaceJoined"
name: 'v1.WorkspaceJoined', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}>(fields: { readonly workspaceId: Schema.String; readonly name: Schema.String;}): Schema.Struct<{ readonly workspaceId: Schema.String; readonly name: 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({ workspaceId: Schema.String
workspaceId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, name: Schema.String
name: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
export const const userEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
userEvents = { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceCreated, workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceJoined }
// Table to store basic user info// Contains only one row as this store is per-user.const const userTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
userTable = import State
State.import SQLite
SQLite.function table<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "user"; columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; };} & Partial<Partial<{ indexes: Index[];}>>): 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: "user"
name: 'user', columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}
columns: { // Assuming username is unique and used as the identifier username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
username: 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 }), },})
// Table to track which workspaces this user is part ofconst const userWorkspacesTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspacesTable = import State
State.import SQLite
SQLite.function table<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "userWorkspaces"; columns: { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; 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: "userWorkspaces"
name: 'userWorkspaces', columns: { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
workspaceId: 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 }), name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
name: 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(), // Could add role/permissions here later },})
export const const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables = { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
user: const userTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
userTable, userWorkspaces: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspaces: const userWorkspacesTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspacesTable }
const const materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>>; "v1.WorkspaceJoined": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>;}>(_eventDefRecord: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>;}, 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 userEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
userEvents, { // When the user creates or joins a workspace, add it to their workspace table 'v1.WorkspaceCreated': ({ workspaceId: string
workspaceId, name: string
name }) => const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables.userWorkspaces: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspaces.insert: (values: { readonly workspaceId: string; readonly name: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.Codec<string, string, never, never>; readonly name: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; ... 4 more ...; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ workspaceId: string
workspaceId, name: string
name }), 'v1.WorkspaceJoined': ({ workspaceId: string
workspaceId, name: string
name }) => const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables.userWorkspaces: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspaces.insert: (values: { readonly workspaceId: string; readonly name: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.Codec<string, string, never, never>; readonly name: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; ... 4 more ...; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ workspaceId: string
workspaceId, name: string
name }),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
tables: const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables, materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>>; "v1.WorkspaceJoined": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; }; state: InternalState;}>
schema = makeSchema<{ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; }; state: InternalState;}>(inputSchema: { events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
events: const userEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
userEvents, state: InternalState
state })Workspace store:
import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, import State
State } from '@livestore/livestore'
// Emitted when a new workspace is created (originates this store)const const workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">>
workspaceCreated = import Events
Events.synced<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">>(args: { name: "v1.WorkspaceCreated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>, 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.WorkspaceCreated"
name: 'v1.WorkspaceCreated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}>(fields: { readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}): Schema.Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: 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({ workspaceId: Schema.String
workspaceId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, name: Schema.String
name: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, createdByUsername: Schema.String
createdByUsername: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, }),})
// Emitted when a todo item is added to this workspaceconst const todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoAdded = import Events
Events.synced<"v1.TodoAdded", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">>(args: { name: "v1.TodoAdded"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: 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.TodoAdded"
name: 'v1.TodoAdded', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly todoId: Schema.String; readonly text: Schema.String;}>(fields: { readonly todoId: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly todoId: 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({ todoId: Schema.String
todoId: 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 }),})
// Emitted when a todo item is marked as completedconst const todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">>
todoCompleted = import Events
Events.synced<"v1.TodoCompleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">>(args: { name: "v1.TodoCompleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly todoId: 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.TodoCompleted"
name: 'v1.TodoCompleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly todoId: Schema.String;}>(fields: { readonly todoId: Schema.String;}): Schema.Struct<{ readonly todoId: 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({ todoId: Schema.String
todoId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
// Emitted when a todo item is deleted (soft delete)const const todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>
todoDeleted = import Events
Events.synced<"v1.TodoDeleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>(args: { name: "v1.TodoDeleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString; }, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString; }, "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.TodoDeleted"
name: 'v1.TodoDeleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}>(fields: { readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}>
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({ todoId: Schema.String
todoId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, deletedAt: Schema.DateFromString
deletedAt: import Schema
Schema.const DateFromString: Schema.DateFromString
Type-level representation of
DateFromString
.
Schema that decodes a string into a JavaScript Date.
When to use
Use to model string-encoded dates that decode to JavaScript Date objects
and encode back to strings.
Details
Decoding:
The string is passed to JavaScript Date construction.
Encoding:
A valid Date is encoded as an ISO string; an invalid Date is encoded as
"Invalid Date".
Gotchas
Invalid date strings can decode to invalid Date instances.
DateFromString.Bottom<unknown, unknown, unknown, unknown, Declaration, decodeTo<Date, String, never, never>, unknown, unknown, readonly [], unknown, "readonly", "required", "no-default", "readonly", "required">.check(checks_0: Check<Date>, ...checks: Check<Date>[]): Schema.DateFromString
check(import Schema
Schema.function isDateValid(annotations?: Schema.Annotations.Filter): Filter<globalThis.Date>
Validates that a Date object represents a valid date (not an invalid date
like new Date("invalid")).
Details
JSON Schema:
This check does not have a direct JSON Schema equivalent, as JSON Schema
validates date strings, not Date objects.
Arbitrary:
When generating test data with fast-check, this applies a valid: true
constraint to ensure generated Date objects are valid.
isDateValid()), }),})
// Emitted when a new user joins this workspaceconst const userJoined: State.SQLite.EventDef<"v1.UserJoined", Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">>
userJoined = import Events
Events.synced<"v1.UserJoined", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">>(args: { name: "v1.UserJoined"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly username: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly username: 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.UserJoined"
name: 'v1.UserJoined', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly username: Schema.String;}>(fields: { readonly username: Schema.String;}): Schema.Struct<{ readonly username: 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({ username: Schema.String
username: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
export const const workspaceEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}
workspaceEvents = { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">>
workspaceCreated, todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoAdded, todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">>
todoCompleted, todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>
todoDeleted, userJoined: State.SQLite.EventDef<"v1.UserJoined", Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">>
userJoined }
// Table for the workspace itself (only one row as this store is per-workspace)const const workspaceTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspaceTable = import State
State.import SQLite
SQLite.function table<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}, 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: "workspace"
name: 'workspace', columns: { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
workspaceId: 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 }), name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
name: 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(), createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
createdByUsername: 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(), },})
// Table for the todo items in this workspaceconst const todosTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todosTable = import State
State.import SQLite
SQLite.function table<"todos", { readonly todoId: { 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 deletedAt: { ...; };}, 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 todoId: { 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 deletedAt: { ...; };}
columns: { todoId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
todoId: 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 }), // Using soft delete by adding a deletedAt timestamp deletedAt: { columnType: "integer"; schema: Schema.Codec<Date | null, number | null, never, never>; default: None<never>; nullable: true; primaryKey: false; autoIncrement: false;}
deletedAt: import State
State.import SQLite
SQLite.const integer: <number, Date, true, typeof NoDefault, false, false>(args: { schema?: Schema.Codec<Date, number, never, never>; default?: typeof NoDefault; nullable?: true; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Codec<Date | null, number | null, never, never>; default: None<never>; nullable: true; primaryKey: false; autoIncrement: false;} (+1 overload)
integer({ nullable?: true
nullable: true, schema?: Schema.Codec<Date, number, never, never>
schema: import Schema
Schema.const DateFromMillis: Schema.DateFromMillis
Type-level representation of
DateFromMillis
.
Schema that decodes epoch milliseconds into a JavaScript Date.
When to use
Use to model numeric millisecond timestamps that decode to JavaScript Date
objects and encode back to numbers.
Details
Decoding:
A number of milliseconds since the Unix epoch is decoded as a Date.
Encoding:
A Date is encoded as its millisecond timestamp.
Gotchas
This schema accepts any number, including NaN, Infinity, and -Infinity.
Those values decode to invalid Date instances.
DateFromMillis }), },})
// Table for members of this workspaceconst const membersTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
membersTable = import State
State.import SQLite
SQLite.function table<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "members"; columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; };} & Partial<Partial<{ indexes: Index[];}>>): 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: "members"
name: 'members', columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}
columns: { username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
username: 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 }), // Could add role/permissions here later },})
export const const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables = { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspace: const workspaceTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspaceTable, todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos: const todosTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todosTable, members: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
members: const membersTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
membersTable }
const const materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>>; "v1.TodoAdded": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>; "v1.TodoCompleted": State.SQLite.Materializer<...>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.UserJoined": State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}>(_eventDefRecord: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: 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 workspaceEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}
workspaceEvents, { 'v1.WorkspaceCreated': ({ workspaceId: string
workspaceId, name: string
name, createdByUsername: string
createdByUsername }) => [ const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspace.insert: (values: { readonly workspaceId: string; readonly name: string; readonly createdByUsername: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.Codec<string, string, never, never>; readonly name: Schema.Codec<string, string, never, never>; readonly createdByUsername: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<...>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { ...; }; readonly createdByUsername: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ workspaceId: string
workspaceId, name: string
name, createdByUsername: string
createdByUsername }), // Add the creator as the first member const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.members: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
members.insert: (values: { readonly username: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly username: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ username: string
username: createdByUsername: string
createdByUsername }), ], 'v1.TodoAdded': ({ todoId: string
todoId, text: string
text }) => const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos.insert: (values: { readonly todoId: string; readonly text: string; readonly deletedAt?: Date | null; readonly completed?: boolean;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<...>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ todoId: string
todoId, text: string
text }), 'v1.TodoCompleted': ({ todoId: string
todoId }) => const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos.update: (values: Partial<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly todoId: string | { op: Exclude<QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase<any, any>, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string; } | { ...; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+3 overloads)
where({ todoId?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
todoId }), 'v1.TodoDeleted': ({ todoId: string
todoId, deletedAt: Date
deletedAt }) => const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos.update: (values: Partial<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly todoId: string | { op: Exclude<QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase<any, any>, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string; } | { ...; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+3 overloads)
where({ todoId?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
todoId }), 'v1.UserJoined': ({ username: string
username }) => const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.members: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
members.insert: (values: { readonly username: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly username: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ username: string
username }),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
tables: const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables, materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>>; "v1.TodoAdded": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>; "v1.TodoCompleted": State.SQLite.Materializer<...>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.UserJoined": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>; }; state: InternalState;}>(inputSchema: { events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}
events: const workspaceEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}
workspaceEvents, state: InternalState
state })Store configuration
Section titled “Store configuration”Now that we’ve defined our schemas, let’s configure the stores:
Workspace store:
import { const makePersistedAdapter: (options: WebAdapterOptions) => Adapter
Creates a web adapter with persistent storage (currently only supports OPFS).
Requires both a web worker and a shared worker.
On browsers without SharedWorker support (e.g. Android Chrome), this adapter
automatically falls back to single-tab mode. In single-tab mode:
- Each tab runs independently with its own leader worker
- Multi-tab synchronization is not available
- Devtools are not supported
makePersistedAdapter } from '@livestore/adapter-web'import const sharedWorker: new (options?: { name?: string;}) => SharedWorker
sharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'import { const storeOptions: <TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<Json, Json, never, never>>(options: RegistryStoreOptions<TSchema, TContext, TSyncPayloadSchema>) => RegistryStoreOptions<TSchema, TContext, TSyncPayloadSchema>
Helper for defining reusable store options with full type inference. Returns
options that can be passed to useStore() or storeRegistry.preload().
storeOptions } from '@livestore/livestore'
import { import schema
schema } from './workspace.schema.ts'import const worker: new (options?: { name?: string;}) => Worker
worker from './workspace.worker.ts?worker'
const const adapter: Adapter
adapter = function makePersistedAdapter(options: WebAdapterOptions): Adapter
Creates a web adapter with persistent storage (currently only supports OPFS).
Requires both a web worker and a shared worker.
On browsers without SharedWorker support (e.g. Android Chrome), this adapter
automatically falls back to single-tab mode. In single-tab mode:
- Each tab runs independently with its own leader worker
- Multi-tab synchronization is not available
- Devtools are not supported
makePersistedAdapter({ storage: { readonly type: "opfs"; readonly directory?: string | undefined;}
Specifies where to persist data for this adapter
storage: { type: "opfs"
type: 'opfs' }, worker: ((options: { name: string;}) => globalThis.Worker) | (new (options: { name: string;}) => globalThis.Worker)
worker, sharedWorker: ((options: { name: string;}) => globalThis.SharedWorker) | (new (options: { name: string;}) => globalThis.SharedWorker)
This is mostly an implementation detail and needed to be exposed into app code
due to a current Vite limitation (https://github.com/vitejs/vite/issues/8427).
In most cases this should look like:
import LiveStoreSharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'
const adapter = makePersistedAdapter({ sharedWorker: LiveStoreSharedWorker, // ...})
sharedWorker,})
// Define workspace store configuration// Each workspace gets its own isolated store instanceexport const const workspaceStoreOptions: (workspaceId: string) => RegistryStoreOptions<any, {}, Codec<Json, Json, never, never>>
workspaceStoreOptions = (workspaceId: string
workspaceId: string) => storeOptions<any, {}, Codec<Json, Json, never, never>>(options: RegistryStoreOptions<any, {}, Codec<Json, Json, never, never>>): RegistryStoreOptions<any, {}, Codec<Json, Json, never, never>>
Helper for defining reusable store options with full type inference. Returns
options that can be passed to useStore() or storeRegistry.preload().
storeOptions({ CreateStoreOptions<TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<Json, Json, never, never>>.storeId: string
Unique identifier for the Store instance, stable for its lifetime.
- Valid characters: Only alphanumeric characters, underscores (
_), and hyphens (-)
are allowed. Must match /^[a-zA-Z0-9_-]+$/.
- Globally unique: Use globally unique IDs (e.g., nanoid) to prevent collisions across stores.
- Use namespaces: Prefix to avoid collisions and for easier identification when debugging
(e.g.,
app-root, workspace-abc123, issue-456)
storeId: `workspace-${workspaceId: string
workspaceId}`, CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.schema: any
The LiveStore schema defining tables, events, and materializers.
schema, CreateStoreOptions<TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<Json, Json, never, never>>.adapter: Adapter
Adapter used for data storage and synchronization.
adapter, RegistryStoreOptions<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<...>>.unusedCacheTime?: number
The time in milliseconds that this store should remain
in memory after becoming unused. When this store becomes
unused (no active retentions), it will be disposed after this duration.
Stores transition to the unused state as soon as they have no
active retentions, so when all components which use that store
have unmounted.
unusedCacheTime: 60_000, // Keep in memory for 60 seconds after last use })import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, import State
State } from '@livestore/livestore'
// Emitted when a new workspace is created (originates this store)const const workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">>
workspaceCreated = import Events
Events.synced<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">>(args: { name: "v1.WorkspaceCreated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>, 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.WorkspaceCreated"
name: 'v1.WorkspaceCreated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}>(fields: { readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}): Schema.Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: 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({ workspaceId: Schema.String
workspaceId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, name: Schema.String
name: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, createdByUsername: Schema.String
createdByUsername: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, }),})
// Emitted when a todo item is added to this workspaceconst const todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoAdded = import Events
Events.synced<"v1.TodoAdded", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">>(args: { name: "v1.TodoAdded"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: 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.TodoAdded"
name: 'v1.TodoAdded', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly todoId: Schema.String; readonly text: Schema.String;}>(fields: { readonly todoId: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly todoId: 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({ todoId: Schema.String
todoId: 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 }),})
// Emitted when a todo item is marked as completedconst const todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">>
todoCompleted = import Events
Events.synced<"v1.TodoCompleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">>(args: { name: "v1.TodoCompleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly todoId: 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.TodoCompleted"
name: 'v1.TodoCompleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly todoId: Schema.String;}>(fields: { readonly todoId: Schema.String;}): Schema.Struct<{ readonly todoId: 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({ todoId: Schema.String
todoId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
// Emitted when a todo item is deleted (soft delete)const const todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>
todoDeleted = import Events
Events.synced<"v1.TodoDeleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>(args: { name: "v1.TodoDeleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString; }, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString; }, "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.TodoDeleted"
name: 'v1.TodoDeleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}>(fields: { readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}>
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({ todoId: Schema.String
todoId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, deletedAt: Schema.DateFromString
deletedAt: import Schema
Schema.const DateFromString: Schema.DateFromString
Type-level representation of
DateFromString
.
Schema that decodes a string into a JavaScript Date.
When to use
Use to model string-encoded dates that decode to JavaScript Date objects
and encode back to strings.
Details
Decoding:
The string is passed to JavaScript Date construction.
Encoding:
A valid Date is encoded as an ISO string; an invalid Date is encoded as
"Invalid Date".
Gotchas
Invalid date strings can decode to invalid Date instances.
DateFromString.Bottom<unknown, unknown, unknown, unknown, Declaration, decodeTo<Date, String, never, never>, unknown, unknown, readonly [], unknown, "readonly", "required", "no-default", "readonly", "required">.check(checks_0: Check<Date>, ...checks: Check<Date>[]): Schema.DateFromString
check(import Schema
Schema.function isDateValid(annotations?: Schema.Annotations.Filter): Filter<globalThis.Date>
Validates that a Date object represents a valid date (not an invalid date
like new Date("invalid")).
Details
JSON Schema:
This check does not have a direct JSON Schema equivalent, as JSON Schema
validates date strings, not Date objects.
Arbitrary:
When generating test data with fast-check, this applies a valid: true
constraint to ensure generated Date objects are valid.
isDateValid()), }),})
// Emitted when a new user joins this workspaceconst const userJoined: State.SQLite.EventDef<"v1.UserJoined", Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">>
userJoined = import Events
Events.synced<"v1.UserJoined", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">>(args: { name: "v1.UserJoined"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly username: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly username: 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.UserJoined"
name: 'v1.UserJoined', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly username: Schema.String;}>(fields: { readonly username: Schema.String;}): Schema.Struct<{ readonly username: 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({ username: Schema.String
username: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
export const const workspaceEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}
workspaceEvents = { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">>
workspaceCreated, todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoAdded, todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">>
todoCompleted, todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>
todoDeleted, userJoined: State.SQLite.EventDef<"v1.UserJoined", Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">>
userJoined }
// Table for the workspace itself (only one row as this store is per-workspace)const const workspaceTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspaceTable = import State
State.import SQLite
SQLite.function table<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}, 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: "workspace"
name: 'workspace', columns: { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
workspaceId: 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 }), name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
name: 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(), createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
createdByUsername: 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(), },})
// Table for the todo items in this workspaceconst const todosTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todosTable = import State
State.import SQLite
SQLite.function table<"todos", { readonly todoId: { 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 deletedAt: { ...; };}, 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 todoId: { 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 deletedAt: { ...; };}
columns: { todoId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
todoId: 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 }), // Using soft delete by adding a deletedAt timestamp deletedAt: { columnType: "integer"; schema: Schema.Codec<Date | null, number | null, never, never>; default: None<never>; nullable: true; primaryKey: false; autoIncrement: false;}
deletedAt: import State
State.import SQLite
SQLite.const integer: <number, Date, true, typeof NoDefault, false, false>(args: { schema?: Schema.Codec<Date, number, never, never>; default?: typeof NoDefault; nullable?: true; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Codec<Date | null, number | null, never, never>; default: None<never>; nullable: true; primaryKey: false; autoIncrement: false;} (+1 overload)
integer({ nullable?: true
nullable: true, schema?: Schema.Codec<Date, number, never, never>
schema: import Schema
Schema.const DateFromMillis: Schema.DateFromMillis
Type-level representation of
DateFromMillis
.
Schema that decodes epoch milliseconds into a JavaScript Date.
When to use
Use to model numeric millisecond timestamps that decode to JavaScript Date
objects and encode back to numbers.
Details
Decoding:
A number of milliseconds since the Unix epoch is decoded as a Date.
Encoding:
A Date is encoded as its millisecond timestamp.
Gotchas
This schema accepts any number, including NaN, Infinity, and -Infinity.
Those values decode to invalid Date instances.
DateFromMillis }), },})
// Table for members of this workspaceconst const membersTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
membersTable = import State
State.import SQLite
SQLite.function table<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "members"; columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; };} & Partial<Partial<{ indexes: Index[];}>>): 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: "members"
name: 'members', columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}
columns: { username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
username: 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 }), // Could add role/permissions here later },})
export const const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables = { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspace: const workspaceTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspaceTable, todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos: const todosTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todosTable, members: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
members: const membersTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
membersTable }
const const materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>>; "v1.TodoAdded": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>; "v1.TodoCompleted": State.SQLite.Materializer<...>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.UserJoined": State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}>(_eventDefRecord: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: 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 workspaceEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}
workspaceEvents, { 'v1.WorkspaceCreated': ({ workspaceId: string
workspaceId, name: string
name, createdByUsername: string
createdByUsername }) => [ const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspace.insert: (values: { readonly workspaceId: string; readonly name: string; readonly createdByUsername: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.Codec<string, string, never, never>; readonly name: Schema.Codec<string, string, never, never>; readonly createdByUsername: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<...>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { ...; }; readonly createdByUsername: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ workspaceId: string
workspaceId, name: string
name, createdByUsername: string
createdByUsername }), // Add the creator as the first member const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.members: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
members.insert: (values: { readonly username: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly username: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ username: string
username: createdByUsername: string
createdByUsername }), ], 'v1.TodoAdded': ({ todoId: string
todoId, text: string
text }) => const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos.insert: (values: { readonly todoId: string; readonly text: string; readonly deletedAt?: Date | null; readonly completed?: boolean;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<...>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ todoId: string
todoId, text: string
text }), 'v1.TodoCompleted': ({ todoId: string
todoId }) => const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos.update: (values: Partial<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly todoId: string | { op: Exclude<QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase<any, any>, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string; } | { ...; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+3 overloads)
where({ todoId?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
todoId }), 'v1.TodoDeleted': ({ todoId: string
todoId, deletedAt: Date
deletedAt }) => const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos.update: (values: Partial<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly todoId: string | { op: Exclude<QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase<any, any>, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string; } | { ...; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+3 overloads)
where({ todoId?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
todoId }), 'v1.UserJoined': ({ username: string
username }) => const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.members: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
members.insert: (values: { readonly username: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly username: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ username: string
username }),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
tables: const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables, materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>>; "v1.TodoAdded": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>; "v1.TodoCompleted": State.SQLite.Materializer<...>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.UserJoined": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>; }; state: InternalState;}>(inputSchema: { events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}
events: const workspaceEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}
workspaceEvents, state: InternalState
state })User store:
import { const makePersistedAdapter: (options: WebAdapterOptions) => Adapter
Creates a web adapter with persistent storage (currently only supports OPFS).
Requires both a web worker and a shared worker.
On browsers without SharedWorker support (e.g. Android Chrome), this adapter
automatically falls back to single-tab mode. In single-tab mode:
- Each tab runs independently with its own leader worker
- Multi-tab synchronization is not available
- Devtools are not supported
makePersistedAdapter } from '@livestore/adapter-web'import const sharedWorker: new (options?: { name?: string;}) => SharedWorker
sharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'import { const useStore: <TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<Json, Json, never, never>>(options: RegistryStoreOptions<TSchema, TContext, TSyncPayloadSchema>) => Store<TSchema, TContext> & ReactApi
Returns a store instance augmented with hooks (store.useQuery() and store.useClientDocument()) for reactive queries.
useStore } from '@livestore/react'
import { import schema
schema } from './user.schema.ts'import const worker: new (options?: { name?: string;}) => Worker
worker from './user.worker.ts?worker'
const const adapter: Adapter
adapter = function makePersistedAdapter(options: WebAdapterOptions): Adapter
Creates a web adapter with persistent storage (currently only supports OPFS).
Requires both a web worker and a shared worker.
On browsers without SharedWorker support (e.g. Android Chrome), this adapter
automatically falls back to single-tab mode. In single-tab mode:
- Each tab runs independently with its own leader worker
- Multi-tab synchronization is not available
- Devtools are not supported
makePersistedAdapter({ storage: { readonly type: "opfs"; readonly directory?: string | undefined;}
Specifies where to persist data for this adapter
storage: { type: "opfs"
type: 'opfs' }, worker: ((options: { name: string;}) => globalThis.Worker) | (new (options: { name: string;}) => globalThis.Worker)
worker, sharedWorker: ((options: { name: string;}) => globalThis.SharedWorker) | (new (options: { name: string;}) => globalThis.SharedWorker)
This is mostly an implementation detail and needed to be exposed into app code
due to a current Vite limitation (https://github.com/vitejs/vite/issues/8427).
In most cases this should look like:
import LiveStoreSharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'
const adapter = makePersistedAdapter({ sharedWorker: LiveStoreSharedWorker, // ...})
sharedWorker,})
// Hook to access the current user's storeexport const const useCurrentUserStore: () => Store<any, {}> & ReactApi
useCurrentUserStore = () => useStore<any, {}, Codec<Json, Json, never, never>>(options: RegistryStoreOptions<any, {}, Codec<Json, Json, never, never>>): Store<any, {}> & ReactApi
Returns a store instance augmented with hooks (store.useQuery() and store.useClientDocument()) for reactive queries.
useStore({ CreateStoreOptions<TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<Json, Json, never, never>>.storeId: string
Unique identifier for the Store instance, stable for its lifetime.
- Valid characters: Only alphanumeric characters, underscores (
_), and hyphens (-)
are allowed. Must match /^[a-zA-Z0-9_-]+$/.
- Globally unique: Use globally unique IDs (e.g., nanoid) to prevent collisions across stores.
- Use namespaces: Prefix to avoid collisions and for easier identification when debugging
(e.g.,
app-root, workspace-abc123, issue-456)
storeId: 'user-current', // Backend should resolve this to the authenticated user's store CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.schema: any
The LiveStore schema defining tables, events, and materializers.
schema, CreateStoreOptions<TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<Json, Json, never, never>>.adapter: Adapter
Adapter used for data storage and synchronization.
adapter, RegistryStoreOptions<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<...>>.unusedCacheTime?: number
The time in milliseconds that this store should remain
in memory after becoming unused. When this store becomes
unused (no active retentions), it will be disposed after this duration.
Stores transition to the unused state as soon as they have no
active retentions, so when all components which use that store
have unmounted.
unusedCacheTime: var Number: NumberConstructor
An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.
Number.NumberConstructor.POSITIVE_INFINITY: number
A value greater than the largest number that can be represented in JavaScript.
JavaScript displays POSITIVE_INFINITY values as infinity.
POSITIVE_INFINITY, // Keep user store in memory indefinitely })import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, import State
State } from '@livestore/livestore'
// Emitted when this user creates a new workspaceconst const workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceCreated = import Events
Events.synced<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>(args: { name: "v1.WorkspaceCreated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: 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.WorkspaceCreated"
name: 'v1.WorkspaceCreated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}>(fields: { readonly workspaceId: Schema.String; readonly name: Schema.String;}): Schema.Struct<{ readonly workspaceId: Schema.String; readonly name: 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({ workspaceId: Schema.String
workspaceId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, name: Schema.String
name: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
// Emitted when this user joins an existing workspaceconst const workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceJoined = import Events
Events.synced<"v1.WorkspaceJoined", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>(args: { name: "v1.WorkspaceJoined"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: 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.WorkspaceJoined"
name: 'v1.WorkspaceJoined', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}>(fields: { readonly workspaceId: Schema.String; readonly name: Schema.String;}): Schema.Struct<{ readonly workspaceId: Schema.String; readonly name: 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({ workspaceId: Schema.String
workspaceId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, name: Schema.String
name: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
export const const userEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
userEvents = { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceCreated, workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceJoined }
// Table to store basic user info// Contains only one row as this store is per-user.const const userTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
userTable = import State
State.import SQLite
SQLite.function table<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "user"; columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; };} & Partial<Partial<{ indexes: Index[];}>>): 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: "user"
name: 'user', columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}
columns: { // Assuming username is unique and used as the identifier username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
username: 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 }), },})
// Table to track which workspaces this user is part ofconst const userWorkspacesTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspacesTable = import State
State.import SQLite
SQLite.function table<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "userWorkspaces"; columns: { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; 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: "userWorkspaces"
name: 'userWorkspaces', columns: { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
workspaceId: 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 }), name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
name: 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(), // Could add role/permissions here later },})
export const const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables = { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
user: const userTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
userTable, userWorkspaces: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspaces: const userWorkspacesTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspacesTable }
const const materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>>; "v1.WorkspaceJoined": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>;}>(_eventDefRecord: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>;}, 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 userEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
userEvents, { // When the user creates or joins a workspace, add it to their workspace table 'v1.WorkspaceCreated': ({ workspaceId: string
workspaceId, name: string
name }) => const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables.userWorkspaces: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspaces.insert: (values: { readonly workspaceId: string; readonly name: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.Codec<string, string, never, never>; readonly name: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; ... 4 more ...; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ workspaceId: string
workspaceId, name: string
name }), 'v1.WorkspaceJoined': ({ workspaceId: string
workspaceId, name: string
name }) => const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables.userWorkspaces: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspaces.insert: (values: { readonly workspaceId: string; readonly name: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.Codec<string, string, never, never>; readonly name: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; ... 4 more ...; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ workspaceId: string
workspaceId, name: string
name }),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
tables: const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables, materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>>; "v1.WorkspaceJoined": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; }; state: InternalState;}>
schema = makeSchema<{ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; }; state: InternalState;}>(inputSchema: { events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
events: const userEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
userEvents, state: InternalState
state })Set up the store registry
Section titled “Set up the store registry”Create a StoreRegistry and provide it to your React app:
import { type type ReactNode = string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<AwaitedReactNode> | null | undefined
Represents all of the things React can render.
Where
ReactElement
only represents JSX, ReactNode represents everything that can be rendered.
ReactNode, function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>] (+1 overload)
Returns a stateful value, and a function to update it.
useState } from 'react'import { function unstable_batchedUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
unstable_batchedUpdates as function batchUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
batchUpdates } from 'react-dom'
import { class StoreRegistry
Store Registry coordinating store loading, caching, and retention
StoreRegistry } from '@livestore/livestore'import { const StoreRegistryProvider: ({ storeRegistry, children }: StoreRegistryProviderProps) => JSX.Element
React context provider that makes a
StoreRegistry
available to descendant components.
Wrap your application (or a subtree) with this provider to enable
useStore
and
useStoreRegistry
hooks within that tree.
StoreRegistryProvider } from '@livestore/react'
export const const App: ({ children }: { children: ReactNode;}) => JSX.Element
App = ({ children: ReactNode
children }: { children: ReactNode
children: type ReactNode = string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<AwaitedReactNode> | null | undefined
Represents all of the things React can render.
Where
ReactElement
only represents JSX, ReactNode represents everything that can be rendered.
ReactNode }) => { const [const storeRegistry: StoreRegistry
storeRegistry] = useState<StoreRegistry>(initialState: StoreRegistry | (() => StoreRegistry)): [StoreRegistry, Dispatch<SetStateAction<StoreRegistry>>] (+1 overload)
Returns a stateful value, and a function to update it.
useState( () => new new StoreRegistry(config?: StoreRegistryConfig): StoreRegistry
Creates a new StoreRegistry instance.
StoreRegistry({ defaultOptions?: Partial<Pick<RegistryStoreOptions<LiveStoreSchema.Any, {}, Codec<Json, Json, never, never>>, "batchUpdates" | "disableDevtools" | "confirmUnsavedChanges" | "debug" | "otelOptions" | "unusedCacheTime">>
Default options that are applied to all stores when they are loaded.
defaultOptions: { batchUpdates?: (run: () => void) => void
Needed in React so LiveStore can apply multiple events in a single render.
batchUpdates, }, }), )
return <const StoreRegistryProvider: ({ storeRegistry, children }: StoreRegistryProviderProps) => JSX.Element
React context provider that makes a
StoreRegistry
available to descendant components.
Wrap your application (or a subtree) with this provider to enable
useStore
and
useStoreRegistry
hooks within that tree.
StoreRegistryProvider storeRegistry: StoreRegistry
storeRegistry={const storeRegistry: StoreRegistry
storeRegistry}>{children: ReactNode
children}</const StoreRegistryProvider: ({ storeRegistry, children }: StoreRegistryProviderProps) => JSX.Element
React context provider that makes a
StoreRegistry
available to descendant components.
Wrap your application (or a subtree) with this provider to enable
useStore
and
useStoreRegistry
hooks within that tree.
StoreRegistryProvider>}Accessing stores
Section titled “Accessing stores”Use the useStore() hook to access specific workspace instances:
import { function useCallback<T extends Function>(callback: T, deps: DependencyList): T
useCallback will return a memoized version of the callback that only changes if one of the inputs
has changed.
useCallback } from 'react'
import { const queryDb: { <TResultSchema, TResult = TResultSchema>(queryInput: QueryInputRaw<TResultSchema, ReadonlyArray<any>> | QueryBuilder<TResultSchema, any, any>, options?: { map?: (rows: TResultSchema) => TResult; label?: string; deps?: DepKey; }): LiveQueryDef<TResult>; <TResultSchema, TResult = TResultSchema>(queryInput: ((get: GetAtomResult) => QueryInputRaw<TResultSchema, ReadonlyArray<any>>) | ((get: GetAtomResult) => QueryBuilder<TResultSchema, any, any>), options?: { map?: (rows: TResultSchema) => TResult; label?: string; deps?: DepKey; }): LiveQueryDef<TResult>;}
NOTE queryDb is only supposed to read data. Don't use it to insert/update/delete data but use events instead.
When using contextual data when constructing the query, please make sure to include it in the deps option.
queryDb } from '@livestore/livestore'import { const useStore: <TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<Json, Json, never, never>>(options: RegistryStoreOptions<TSchema, TContext, TSyncPayloadSchema>) => Store<TSchema, TContext> & ReactApi
Returns a store instance augmented with hooks (store.useQuery() and store.useClientDocument()) for reactive queries.
useStore } from '@livestore/react'
import { import userTables
userTables } from './user.schema.ts'import { import useCurrentUserStore
useCurrentUserStore } from './user.store.ts'import { import workspaceEvents
workspaceEvents, import workspaceTables
workspaceTables } from './workspace.schema.ts'import { import workspaceStoreOptions
workspaceStoreOptions } from './workspace.store.ts'
// Component that accesses a specific workspace storeexport const const Workspace: ({ workspaceId }: { workspaceId: string;}) => JSX.Element
Workspace = ({ workspaceId: string
workspaceId }: { workspaceId: string
workspaceId: string }) => { const const userStore: any
userStore = import useCurrentUserStore
useCurrentUserStore() const const workspaceStore: Store<LiveStoreSchema<DbSchema, EventDefRecord>, {}> & ReactApi
workspaceStore = useStore<LiveStoreSchema<DbSchema, EventDefRecord>, {}, Codec<Json, Json, never, never>>(options: RegistryStoreOptions<LiveStoreSchema<DbSchema, EventDefRecord>, {}, Codec<Json, Json, never, never>>): Store<LiveStoreSchema<DbSchema, EventDefRecord>, {}> & ReactApi
Returns a store instance augmented with hooks (store.useQuery() and store.useClientDocument()) for reactive queries.
useStore(import workspaceStoreOptions
workspaceStoreOptions(workspaceId: string
workspaceId))
// Check if this workspace exists in user's workspace list const [const knownWorkspace: any
knownWorkspace] = const userStore: any
userStore.any
useQuery(queryDb<unknown, unknown>(queryInput: QueryInputRaw<unknown, readonly any[]> | QueryBuilder<unknown, any, any>, options?: { map?: (rows: unknown) => unknown; label?: string; deps?: DepKey;} | undefined): LiveQueryDef<unknown, "def"> (+1 overload)
NOTE queryDb is only supposed to read data. Don't use it to insert/update/delete data but use events instead.
When using contextual data when constructing the query, please make sure to include it in the deps option.
queryDb(import userTables
userTables.any
userWorkspaces.any
select().any
where({ workspaceId: string
workspaceId })))
// Query workspace data const [const workspace: any
workspace] = const workspaceStore: Store<LiveStoreSchema<DbSchema, EventDefRecord>, {}> & ReactApi
workspaceStore.useQuery: <LiveQueryDef<unknown, "def">>(queryable: LiveQueryDef<unknown, "def">, options?: { store?: Store;}) => unknown
Returns the result of a query and subscribes to future updates.
Example:
const App = () => { const todos = useQuery(queryDb(tables.todos.query.where({ complete: true }))) return <div>{todos.map((todo) => <div key={todo.id}>{todo.title}</div>)}</div>}
useQuery(queryDb<unknown, unknown>(queryInput: QueryInputRaw<unknown, readonly any[]> | QueryBuilder<unknown, any, any>, options?: { map?: (rows: unknown) => unknown; label?: string; deps?: DepKey;} | undefined): LiveQueryDef<unknown, "def"> (+1 overload)
NOTE queryDb is only supposed to read data. Don't use it to insert/update/delete data but use events instead.
When using contextual data when constructing the query, please make sure to include it in the deps option.
queryDb(import workspaceTables
workspaceTables.any
workspace.any
select().any
limit(1))) const const todos: unknown
todos = const workspaceStore: Store<LiveStoreSchema<DbSchema, EventDefRecord>, {}> & ReactApi
workspaceStore.useQuery: <LiveQueryDef<unknown, "def">>(queryable: LiveQueryDef<unknown, "def">, options?: { store?: Store;}) => unknown
Returns the result of a query and subscribes to future updates.
Example:
const App = () => { const todos = useQuery(queryDb(tables.todos.query.where({ complete: true }))) return <div>{todos.map((todo) => <div key={todo.id}>{todo.title}</div>)}</div>}
useQuery(queryDb<unknown, unknown>(queryInput: QueryInputRaw<unknown, readonly any[]> | QueryBuilder<unknown, any, any>, options?: { map?: (rows: unknown) => unknown; label?: string; deps?: DepKey;} | undefined): LiveQueryDef<unknown, "def"> (+1 overload)
NOTE queryDb is only supposed to read data. Don't use it to insert/update/delete data but use events instead.
When using contextual data when constructing the query, please make sure to include it in the deps option.
queryDb(import workspaceTables
workspaceTables.any
todos.any
select()))
// Workspace not in user's list → truly doesn't exist if (const knownWorkspace: any
knownWorkspace == null) return <JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div>Workspace not found</JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div>
// Workspace is in user's list but not yet initialized → loading state if (const workspace: any
workspace == null) return <JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div>Loading workspace...</JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div>
const const addTodo: (text: string) => void
addTodo = useCallback<(text: string) => void>(callback: (text: string) => void, deps: DependencyList): (text: string) => void
useCallback will return a memoized version of the callback that only changes if one of the inputs
has changed.
useCallback( (text: string
text: string) => { const workspaceStore: Store<LiveStoreSchema<DbSchema, EventDefRecord>, {}> & ReactApi
workspaceStore.Store<LiveStoreSchema<DbSchema, EventDefRecord>, {}>.commit: <readonly [any]>(list_0: any) => void (+3 overloads)
commit( import workspaceEvents
workspaceEvents.any
todoAdded({ todoId: string
todoId: `todo-${var Date: DateConstructor
Enables basic storage and retrieval of dates and times.
Date.DateConstructor.now(): number
Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC).
now()}`, text: string
text, }), ) }, [const workspaceStore: Store<LiveStoreSchema<DbSchema, EventDefRecord>, {}> & ReactApi
workspaceStore], )
const const addNewTodo: () => void
addNewTodo = useCallback<() => void>(callback: () => void, deps: DependencyList): () => void
useCallback will return a memoized version of the callback that only changes if one of the inputs
has changed.
useCallback(() => const addTodo: (text: string) => void
addTodo('New todo'), [const addTodo: (text: string) => void
addTodo])
return ( <JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> <JSX.IntrinsicElements.h2: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>
h2>{const workspace: any
workspace.any
name}</JSX.IntrinsicElements.h2: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>
h2> <JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>Created by: {const workspace: any
workspace.any
createdByUsername}</JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p> <JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>Store ID: {const workspaceStore: Store<LiveStoreSchema<DbSchema, EventDefRecord>, {}> & ReactApi
workspaceStore.Store<LiveStoreSchema<DbSchema, EventDefRecord>, {}>.storeId: string
Unique identifier for this Store instance, stable for its lifetime.
storeId}</JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p>
<JSX.IntrinsicElements.h3: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>
h3>Todos ({const todos: unknown
todos.any
length})</JSX.IntrinsicElements.h3: DetailedHTMLProps<HTMLAttributes<HTMLHeadingElement>, HTMLHeadingElement>
h3> <JSX.IntrinsicElements.ul: DetailedHTMLProps<HTMLAttributes<HTMLUListElement>, HTMLUListElement>
ul> {const todos: unknown
todos.any
map((todo: any
todo) => ( <JSX.IntrinsicElements.li: DetailedHTMLProps<LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>
li Attributes.key?: Key | null | undefined
key={todo: any
todo.any
todoId}> {todo: any
todo.any
text} {todo: any
todo.any
completed === true ? '✓' : ''} </JSX.IntrinsicElements.li: DetailedHTMLProps<LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>
li> ))} </JSX.IntrinsicElements.ul: DetailedHTMLProps<HTMLAttributes<HTMLUListElement>, HTMLUListElement>
ul>
<JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button ButtonHTMLAttributes<HTMLButtonElement>.type?: "button" | "submit" | "reset" | undefined
type="button" DOMAttributes<HTMLButtonElement>.onClick?: MouseEventHandler<HTMLButtonElement> | undefined
onClick={const addNewTodo: () => void
addNewTodo}> Add Todo </JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button> </JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div> )}import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, import State
State } from '@livestore/livestore'
// Emitted when this user creates a new workspaceconst const workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceCreated = import Events
Events.synced<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>(args: { name: "v1.WorkspaceCreated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: 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.WorkspaceCreated"
name: 'v1.WorkspaceCreated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}>(fields: { readonly workspaceId: Schema.String; readonly name: Schema.String;}): Schema.Struct<{ readonly workspaceId: Schema.String; readonly name: 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({ workspaceId: Schema.String
workspaceId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, name: Schema.String
name: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
// Emitted when this user joins an existing workspaceconst const workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceJoined = import Events
Events.synced<"v1.WorkspaceJoined", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>(args: { name: "v1.WorkspaceJoined"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: 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.WorkspaceJoined"
name: 'v1.WorkspaceJoined', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}>(fields: { readonly workspaceId: Schema.String; readonly name: Schema.String;}): Schema.Struct<{ readonly workspaceId: Schema.String; readonly name: 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({ workspaceId: Schema.String
workspaceId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, name: Schema.String
name: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
export const const userEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
userEvents = { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceCreated, workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String;}, "Encoded">>
workspaceJoined }
// Table to store basic user info// Contains only one row as this store is per-user.const const userTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
userTable = import State
State.import SQLite
SQLite.function table<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "user"; columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; };} & Partial<Partial<{ indexes: Index[];}>>): 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: "user"
name: 'user', columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}
columns: { // Assuming username is unique and used as the identifier username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
username: 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 }), },})
// Table to track which workspaces this user is part ofconst const userWorkspacesTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspacesTable = import State
State.import SQLite
SQLite.function table<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "userWorkspaces"; columns: { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; 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: "userWorkspaces"
name: 'userWorkspaces', columns: { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
workspaceId: 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 }), name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
name: 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(), // Could add role/permissions here later },})
export const const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables = { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
user: const userTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
userTable, userWorkspaces: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspaces: const userWorkspacesTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspacesTable }
const const materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>>; "v1.WorkspaceJoined": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>;}>(_eventDefRecord: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>;}, 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 userEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
userEvents, { // When the user creates or joins a workspace, add it to their workspace table 'v1.WorkspaceCreated': ({ workspaceId: string
workspaceId, name: string
name }) => const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables.userWorkspaces: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspaces.insert: (values: { readonly workspaceId: string; readonly name: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.Codec<string, string, never, never>; readonly name: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; ... 4 more ...; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ workspaceId: string
workspaceId, name: string
name }), 'v1.WorkspaceJoined': ({ workspaceId: string
workspaceId, name: string
name }) => const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables.userWorkspaces: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, Schema.Struct<...>>
userWorkspaces.insert: (values: { readonly workspaceId: string; readonly name: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.Codec<string, string, never, never>; readonly name: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"userWorkspaces", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; ... 4 more ...; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ workspaceId: string
workspaceId, name: string
name }),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
tables: const userTables: { user: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"user", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; }>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>; }>>; userWorkspaces: State.SQLite.TableDef<...>;}
userTables, materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>>; "v1.WorkspaceJoined": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; }; state: InternalState;}>
schema = makeSchema<{ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; }; state: InternalState;}>(inputSchema: { events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
events: const userEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>; workspaceJoined: State.SQLite.EventDef<"v1.WorkspaceJoined", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; }, "Encoded">>;}
userEvents, state: InternalState
state })import { const makePersistedAdapter: (options: WebAdapterOptions) => Adapter
Creates a web adapter with persistent storage (currently only supports OPFS).
Requires both a web worker and a shared worker.
On browsers without SharedWorker support (e.g. Android Chrome), this adapter
automatically falls back to single-tab mode. In single-tab mode:
- Each tab runs independently with its own leader worker
- Multi-tab synchronization is not available
- Devtools are not supported
makePersistedAdapter } from '@livestore/adapter-web'import const sharedWorker: new (options?: { name?: string;}) => SharedWorker
sharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'import { const useStore: <TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<Json, Json, never, never>>(options: RegistryStoreOptions<TSchema, TContext, TSyncPayloadSchema>) => Store<TSchema, TContext> & ReactApi
Returns a store instance augmented with hooks (store.useQuery() and store.useClientDocument()) for reactive queries.
useStore } from '@livestore/react'
import { import schema
schema } from './user.schema.ts'import const worker: new (options?: { name?: string;}) => Worker
worker from './user.worker.ts?worker'
const const adapter: Adapter
adapter = function makePersistedAdapter(options: WebAdapterOptions): Adapter
Creates a web adapter with persistent storage (currently only supports OPFS).
Requires both a web worker and a shared worker.
On browsers without SharedWorker support (e.g. Android Chrome), this adapter
automatically falls back to single-tab mode. In single-tab mode:
- Each tab runs independently with its own leader worker
- Multi-tab synchronization is not available
- Devtools are not supported
makePersistedAdapter({ storage: { readonly type: "opfs"; readonly directory?: string | undefined;}
Specifies where to persist data for this adapter
storage: { type: "opfs"
type: 'opfs' }, worker: ((options: { name: string;}) => globalThis.Worker) | (new (options: { name: string;}) => globalThis.Worker)
worker, sharedWorker: ((options: { name: string;}) => globalThis.SharedWorker) | (new (options: { name: string;}) => globalThis.SharedWorker)
This is mostly an implementation detail and needed to be exposed into app code
due to a current Vite limitation (https://github.com/vitejs/vite/issues/8427).
In most cases this should look like:
import LiveStoreSharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'
const adapter = makePersistedAdapter({ sharedWorker: LiveStoreSharedWorker, // ...})
sharedWorker,})
// Hook to access the current user's storeexport const const useCurrentUserStore: () => Store<any, {}> & ReactApi
useCurrentUserStore = () => useStore<any, {}, Codec<Json, Json, never, never>>(options: RegistryStoreOptions<any, {}, Codec<Json, Json, never, never>>): Store<any, {}> & ReactApi
Returns a store instance augmented with hooks (store.useQuery() and store.useClientDocument()) for reactive queries.
useStore({ CreateStoreOptions<TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<Json, Json, never, never>>.storeId: string
Unique identifier for the Store instance, stable for its lifetime.
- Valid characters: Only alphanumeric characters, underscores (
_), and hyphens (-)
are allowed. Must match /^[a-zA-Z0-9_-]+$/.
- Globally unique: Use globally unique IDs (e.g., nanoid) to prevent collisions across stores.
- Use namespaces: Prefix to avoid collisions and for easier identification when debugging
(e.g.,
app-root, workspace-abc123, issue-456)
storeId: 'user-current', // Backend should resolve this to the authenticated user's store CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.schema: any
The LiveStore schema defining tables, events, and materializers.
schema, CreateStoreOptions<TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<Json, Json, never, never>>.adapter: Adapter
Adapter used for data storage and synchronization.
adapter, RegistryStoreOptions<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}, TSyncPayloadSchema extends Codec<Json, Json> = Codec<...>>.unusedCacheTime?: number
The time in milliseconds that this store should remain
in memory after becoming unused. When this store becomes
unused (no active retentions), it will be disposed after this duration.
Stores transition to the unused state as soon as they have no
active retentions, so when all components which use that store
have unmounted.
unusedCacheTime: var Number: NumberConstructor
An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers.
Number.NumberConstructor.POSITIVE_INFINITY: number
A value greater than the largest number that can be represented in JavaScript.
JavaScript displays POSITIVE_INFINITY values as infinity.
POSITIVE_INFINITY, // Keep user store in memory indefinitely })import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, import State
State } from '@livestore/livestore'
// Emitted when a new workspace is created (originates this store)const const workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">>
workspaceCreated = import Events
Events.synced<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">>(args: { name: "v1.WorkspaceCreated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>, 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.WorkspaceCreated"
name: 'v1.WorkspaceCreated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}>(fields: { readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}): Schema.Struct<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: 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({ workspaceId: Schema.String
workspaceId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, name: Schema.String
name: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, createdByUsername: Schema.String
createdByUsername: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, }),})
// Emitted when a todo item is added to this workspaceconst const todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoAdded = import Events
Events.synced<"v1.TodoAdded", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">>(args: { name: "v1.TodoAdded"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: 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.TodoAdded"
name: 'v1.TodoAdded', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly todoId: Schema.String; readonly text: Schema.String;}>(fields: { readonly todoId: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly todoId: 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({ todoId: Schema.String
todoId: 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 }),})
// Emitted when a todo item is marked as completedconst const todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">>
todoCompleted = import Events
Events.synced<"v1.TodoCompleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">>(args: { name: "v1.TodoCompleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly todoId: 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.TodoCompleted"
name: 'v1.TodoCompleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly todoId: Schema.String;}>(fields: { readonly todoId: Schema.String;}): Schema.Struct<{ readonly todoId: 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({ todoId: Schema.String
todoId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
// Emitted when a todo item is deleted (soft delete)const const todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>
todoDeleted = import Events
Events.synced<"v1.TodoDeleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>(args: { name: "v1.TodoDeleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString; }, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString; }, "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.TodoDeleted"
name: 'v1.TodoDeleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}>(fields: { readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}>
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({ todoId: Schema.String
todoId: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, deletedAt: Schema.DateFromString
deletedAt: import Schema
Schema.const DateFromString: Schema.DateFromString
Type-level representation of
DateFromString
.
Schema that decodes a string into a JavaScript Date.
When to use
Use to model string-encoded dates that decode to JavaScript Date objects
and encode back to strings.
Details
Decoding:
The string is passed to JavaScript Date construction.
Encoding:
A valid Date is encoded as an ISO string; an invalid Date is encoded as
"Invalid Date".
Gotchas
Invalid date strings can decode to invalid Date instances.
DateFromString.Bottom<unknown, unknown, unknown, unknown, Declaration, decodeTo<Date, String, never, never>, unknown, unknown, readonly [], unknown, "readonly", "required", "no-default", "readonly", "required">.check(checks_0: Check<Date>, ...checks: Check<Date>[]): Schema.DateFromString
check(import Schema
Schema.function isDateValid(annotations?: Schema.Annotations.Filter): Filter<globalThis.Date>
Validates that a Date object represents a valid date (not an invalid date
like new Date("invalid")).
Details
JSON Schema:
This check does not have a direct JSON Schema equivalent, as JSON Schema
validates date strings, not Date objects.
Arbitrary:
When generating test data with fast-check, this applies a valid: true
constraint to ensure generated Date objects are valid.
isDateValid()), }),})
// Emitted when a new user joins this workspaceconst const userJoined: State.SQLite.EventDef<"v1.UserJoined", Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">>
userJoined = import Events
Events.synced<"v1.UserJoined", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">>(args: { name: "v1.UserJoined"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly username: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly username: 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.UserJoined"
name: 'v1.UserJoined', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly username: Schema.String;}>(fields: { readonly username: Schema.String;}): Schema.Struct<{ readonly username: 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({ username: Schema.String
username: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }),})
export const const workspaceEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}
workspaceEvents = { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String;}, "Encoded">>
workspaceCreated, todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoAdded, todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String;}, "Encoded">>
todoCompleted, todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>
todoDeleted, userJoined: State.SQLite.EventDef<"v1.UserJoined", Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly username: Schema.String;}, "Encoded">>
userJoined }
// Table for the workspace itself (only one row as this store is per-workspace)const const workspaceTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspaceTable = import State
State.import SQLite
SQLite.function table<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}, 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: "workspace"
name: 'workspace', columns: { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}
columns: { workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
workspaceId: 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 }), name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
name: 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(), createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false;}
createdByUsername: 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(), },})
// Table for the todo items in this workspaceconst const todosTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todosTable = import State
State.import SQLite
SQLite.function table<"todos", { readonly todoId: { 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 deletedAt: { ...; };}, 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 todoId: { 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 deletedAt: { ...; };}
columns: { todoId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
todoId: 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 }), // Using soft delete by adding a deletedAt timestamp deletedAt: { columnType: "integer"; schema: Schema.Codec<Date | null, number | null, never, never>; default: None<never>; nullable: true; primaryKey: false; autoIncrement: false;}
deletedAt: import State
State.import SQLite
SQLite.const integer: <number, Date, true, typeof NoDefault, false, false>(args: { schema?: Schema.Codec<Date, number, never, never>; default?: typeof NoDefault; nullable?: true; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Codec<Date | null, number | null, never, never>; default: None<never>; nullable: true; primaryKey: false; autoIncrement: false;} (+1 overload)
integer({ nullable?: true
nullable: true, schema?: Schema.Codec<Date, number, never, never>
schema: import Schema
Schema.const DateFromMillis: Schema.DateFromMillis
Type-level representation of
DateFromMillis
.
Schema that decodes epoch milliseconds into a JavaScript Date.
When to use
Use to model numeric millisecond timestamps that decode to JavaScript Date
objects and encode back to numbers.
Details
Decoding:
A number of milliseconds since the Unix epoch is decoded as a Date.
Encoding:
A Date is encoded as its millisecond timestamp.
Gotchas
This schema accepts any number, including NaN, Infinity, and -Infinity.
Those values decode to invalid Date instances.
DateFromMillis }), },})
// Table for members of this workspaceconst const membersTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
membersTable = import State
State.import SQLite
SQLite.function table<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}, Partial<{ indexes: Index[];}>>(args: { name: "members"; columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; };} & Partial<Partial<{ indexes: Index[];}>>): 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: "members"
name: 'members', columns: { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}
columns: { username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
username: 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 }), // Could add role/permissions here later },})
export const const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables = { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspace: const workspaceTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspaceTable, todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos: const todosTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todosTable, members: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
members: const membersTable: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
membersTable }
const const materializers: { "v1.WorkspaceCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>>; "v1.TodoAdded": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>>; "v1.TodoCompleted": State.SQLite.Materializer<...>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.UserJoined": State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}>(_eventDefRecord: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: 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 workspaceEvents: { workspaceCreated: State.SQLite.EventDef<"v1.WorkspaceCreated", Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly workspaceId: Schema.String; readonly name: Schema.String; readonly createdByUsername: Schema.String; }, "Encoded">>; todoAdded: State.SQLite.EventDef<"v1.TodoAdded", Schema.Struct.ReadonlySide<{ readonly todoId: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<...>>; todoCompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; userJoined: State.SQLite.EventDef<...>;}
workspaceEvents, { 'v1.WorkspaceCreated': ({ workspaceId: string
workspaceId, name: string
name, createdByUsername: string
createdByUsername }) => [ const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
workspace.insert: (values: { readonly workspaceId: string; readonly name: string; readonly createdByUsername: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly workspaceId: Schema.Codec<string, string, never, never>; readonly name: Schema.Codec<string, string, never, never>; readonly createdByUsername: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<...>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { ...; }; readonly createdByUsername: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ workspaceId: string
workspaceId, name: string
name, createdByUsername: string
createdByUsername }), // Add the creator as the first member const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.members: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, Schema.Struct<{ readonly username: Schema.Codec<string, string, never, never>;}>>
members.insert: (values: { readonly username: string;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly username: Schema.Codec<string, string, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"members", { readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>, State.SQLite.WithDefaults<{ readonly username: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; };}>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ username: string
username: createdByUsername: string
createdByUsername }), ], 'v1.TodoAdded': ({ todoId: string
todoId, text: string
text }) => const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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 deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>
todos.insert: (values: { readonly todoId: string; readonly text: string; readonly deletedAt?: Date | null; readonly completed?: boolean;}) => QueryBuilder<readonly Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly todoId: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<...>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ todoId: string
todoId, text: string
text }), 'v1.TodoCompleted': ({ todoId: string
todoId }) => const workspaceTables: { workspace: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"workspace", { readonly workspaceId: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly name: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly createdByUsername: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: false; autoIncrement: false; }; }>, State.SQLite.WithDefaults<...>, Schema.Struct<...>>; todos: State.SQLite.TableDef<...>; members: State.SQLite.TableDef<...>;}
workspaceTables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly todoId: { 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