Expo
Prerequisites
Section titled “Prerequisites”- Recommended: Bun 1.2 or higher
- Node.js 23.0.0 or higher
To use LiveStore with Expo, ensure your project has the New Architecture enabled. This is required for transactional state updates.
Option A: Quick start
Section titled “Option A: Quick start”For a quick start we recommend using our template app following the steps below.
For existing projects see Existing project setup.
-
Set up project from template
Terminal window bunx @livestore/cli@dev create --example expo-todomvc-sync-cf livestore-appTerminal window pnpm dlx @livestore/cli@dev create --example expo-todomvc-sync-cf livestore-appTerminal window npx @livestore/cli@dev create --example expo-todomvc-sync-cf livestore-appTerminal window yarn dlx @livestore/cli@dev create --example expo-todomvc-sync-cf livestore-appReplace
livestore-appwith your desired app name. -
Install dependencies
It’s strongly recommended to use
bunorpnpmfor the simplest and most reliable dependency setup (see note on package management for more details).Terminal window bun installTerminal window pnpm install --node-linker=hoistedMake sure to use
--node-linker=hoistedwhen installing dependencies in your project or add it to your.npmrcfile..npmrc nodeLinker=hoistedHopefully Expo will also support non-hoisted setups in the future.
Terminal window npm installWhen using
yarn, make sure you’re using Yarn 4 or higher with thenode-moduleslinker.Terminal window yarn set version stableyarn config set nodeLinker node-modulesyarn installPro tip: You can use direnv to manage environment variables.
-
Run the app
Terminal window bun startTerminal window pnpm startTerminal window npm run startTerminal window yarn startIn a new terminal, start the Cloudflare Worker (for the sync backend):
Terminal window bun wrangler:devTerminal window pnpm wrangler:devTerminal window npm run wrangler:devTerminal window yarn wrangler:dev
Option B: Existing project setup
Section titled “Option B: Existing project setup”-
Install dependencies
Terminal window bun install @livestore/devtools-expo@0.5.0-dev.0 @livestore/adapter-expo@0.5.0-dev.0 @livestore/livestore@0.5.0-dev.0 @livestore/react@0.5.0-dev.0 @livestore/sync-cf/client@0.5.0-dev.0 @livestore/peer-deps@0.5.0-dev.0 expo-sqliteTerminal window pnpm install @livestore/devtools-expo@0.5.0-dev.0 @livestore/adapter-expo@0.5.0-dev.0 @livestore/livestore@0.5.0-dev.0 @livestore/react@0.5.0-dev.0 @livestore/sync-cf/client@0.5.0-dev.0 @livestore/peer-deps@0.5.0-dev.0 expo-sqliteTerminal window npm install @livestore/devtools-expo@0.5.0-dev.0 @livestore/adapter-expo@0.5.0-dev.0 @livestore/livestore@0.5.0-dev.0 @livestore/react@0.5.0-dev.0 @livestore/sync-cf/client@0.5.0-dev.0 @livestore/peer-deps@0.5.0-dev.0 expo-sqliteTerminal window yarn add @livestore/devtools-expo@0.5.0-dev.0 @livestore/adapter-expo@0.5.0-dev.0 @livestore/livestore@0.5.0-dev.0 @livestore/react@0.5.0-dev.0 @livestore/sync-cf/client@0.5.0-dev.0 @livestore/peer-deps@0.5.0-dev.0 expo-sqlite -
Add Vite meta plugin to babel config file
LiveStore Devtools uses Vite. This plugin emulates Vite’s
import.meta.envfunctionality.Terminal window bun add -d babel-plugin-transform-vite-meta-envTerminal window pnpm add -D babel-plugin-transform-vite-meta-envTerminal window yarn add -D babel-plugin-transform-vite-meta-envTerminal window npm install --save-dev babel-plugin-transform-vite-meta-envIn your
babel.config.jsfile, add the plugin as follows:babel.config.js module.exports = (api) => {api.cache(true)return {presets: [['babel-preset-expo', { unstable_transformImportMeta: true }]],plugins: ['babel-plugin-transform-vite-meta-env', '@babel/plugin-syntax-import-attributes'],}} -
Update Metro config
Add the following code to your
metro.config.jsfile:metro.config.js // Learn more https://docs.expo.io/guides/customizing-metroconst { getDefaultConfig } = require('expo/metro-config')const { addLiveStoreDevtoolsMiddleware } = require('@livestore/devtools-expo')const path = require('node:path')/** @type {import('expo/metro-config').MetroConfig} */const config = getDefaultConfig(__dirname)// Needed for monorepo setup (can be removed in standalone projects)if (process.env.MONOREPO_ROOT) {config.watchFolders = [path.resolve(process.env.MONOREPO_ROOT)]}addLiveStoreDevtoolsMiddleware(config, {schemaPath: './src/livestore/schema.ts',viteConfig: (viteConfig) => {viteConfig.server.fs ??= {}viteConfig.server.fs.strict = falseviteConfig.optimizeDeps ??= {}viteConfig.optimizeDeps.force = truereturn viteConfig},})module.exports = config
Define your schema
Section titled “Define your schema”Create a file named schema.ts inside the src/livestore folder. This file defines your LiveStore schema consisting of your app’s event definitions (describing how data changes), derived state (i.e. SQLite tables), and materializers (how state is derived from events).
Here’s an example schema:
import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, type SessionIdSymbol = typeof SessionIdSymbolconst SessionIdSymbol: typeof SessionIdSymbol
Can be used in queries to refer to the current session id.
Will be replaced with the actual session id at runtime.
In client document table:
const uiState = State.SQLite.clientDocument({ name: 'ui_state', schema: Schema.Struct({ theme: Schema.Literals(['dark', 'light', 'system']), user: Schema.String, showToolbar: Schema.Boolean, }), default: { value: defaultFrontendState, id: SessionIdSymbol },})
Or in a client document query:
const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
SessionIdSymbol, import State
State } from '@livestore/livestore'
export const const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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 id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: <string, string, false, "", false, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: ""; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text({ default?: ""
default: '' }), 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 }), 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 safe integer number of milliseconds since the Unix epoch is decoded as a
Date.
Encoding:
A Date is encoded as its millisecond timestamp.
Gotchas
JavaScript Date supports a narrower range than safe integers, so integers
outside the supported Date range fail decoding.
DateFromMillis }), }, }), uiState: State.SQLite.ClientDocumentTableDef<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiState: import State
State.import SQLite
SQLite.clientDocument<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly name: "uiState"; readonly schema: Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>; }>; readonly default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>({ name, schema: valueSchema, ...inputOptions }: { name: "uiState"; schema: Schema.Codec<{ readonly newTodoText: string; readonly filter: "completed" | ... 1 more ... | "active"; }, { ...; }, never, never>;} & { readonly name: "uiState"; readonly schema: Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>; }>; readonly default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; }; };}): State.SQLite.ClientDocumentTableDef<...>export clientDocument
Special:
- Synced across client sessions (e.g. tabs) but not across different clients
- Derived setters
- Emits client-only events
- Has implicit setter-materializers
- Similar to
React.useState (except it's persisted)
Careful:
- When changing the table definitions in a non-backwards compatible way, the state might be lost without
explicit materializers to handle the old auto-generated events
Usage:
// Querying data// `'some-id'` can be ommited for SessionIdSymbolstore.queryDb(clientDocumentTable.get('some-id'))
// Setting data// Again, `'some-id'` can be ommited for SessionIdSymbolstore.commit(clientDocumentTable.set({ someField: 'some-value' }, 'some-id'))
clientDocument({ name: "uiState"
name: 'uiState', schema: Schema.Codec<{ readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, never, never> & Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>
schema: import Schema
Schema.function Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>(fields: { readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}): Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>
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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ newTodoText: Schema.String
newTodoText: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, filter: Schema.Literals<readonly ["all", "active", "completed"]>
filter: import Schema
Schema.function Literals<readonly ["all", "active", "completed"]>(literals: readonly ["all", "active", "completed"]): Schema.Literals<readonly ["all", "active", "completed"]>
Creates a union schema from an array of literal values.
Example (Defining status codes)
import { Schema } from "effect"
const schema = Schema.Literals(["active", "inactive", "pending"])Schema.decodeSync(schema)("active") // => "active"
Literals(['all', 'active', 'completed']) }), default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; };}
default: { id: typeof SessionIdSymbol
id: const SessionIdSymbol: typeof SessionIdSymbol
Can be used in queries to refer to the current session id.
Will be replaced with the actual session id at runtime.
In client document table:
const uiState = State.SQLite.clientDocument({ name: 'ui_state', schema: Schema.Struct({ theme: Schema.Literals(['dark', 'light', 'system']), user: Schema.String, showToolbar: Schema.Boolean, }), default: { value: defaultFrontendState, id: SessionIdSymbol },})
Or in a client document query:
const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
SessionIdSymbol, value: { readonly newTodoText: ""; readonly filter: "all";}
value: { newTodoText: ""
newTodoText: '', filter: "all"
filter: 'all' } }, }),}
export const const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Codec<{ readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly text: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Codec<{ readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>(fields: { readonly id: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>
todoCompleted: import Events
Events.synced<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoCompleted"; schema: Schema.Codec<{ readonly id: string; }, { readonly id: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>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<{ readonly id: string;}, { readonly id: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String;}>(fields: { readonly id: Schema.String;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>
todoUncompleted: import Events
Events.synced<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoUncompleted"; schema: Schema.Codec<{ readonly id: string; }, { readonly id: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>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.TodoUncompleted"
name: 'v1.TodoUncompleted', schema: Schema.Codec<{ readonly id: string;}, { readonly id: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String;}>(fields: { readonly id: Schema.String;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>
todoDeleted: import Events
Events.synced<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>(args: { name: "v1.TodoDeleted"; schema: Schema.Codec<{ readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>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<{ readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}>(fields: { readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, 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 Date is encoded as an ISO string.
Invalid date strings fail decoding.
DateFromString, }), }), todoClearedCompleted: State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>
todoClearedCompleted: import Events
Events.synced<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>(args: { name: "v1.TodoClearedCompleted"; schema: Schema.Codec<{ readonly deletedAt: Date; }, { readonly deletedAt: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>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.TodoClearedCompleted"
name: 'v1.TodoClearedCompleted', schema: Schema.Codec<{ readonly deletedAt: Date;}, { readonly deletedAt: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly deletedAt: Schema.DateFromString;}>(fields: { readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ 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 Date is encoded as an ISO string.
Invalid date strings fail decoding.
DateFromString }), }), uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiStateSet: const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.uiState: State.SQLite.ClientDocumentTableDef<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiState.ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.Trait<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active"; }, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active"; }, { ...; }>.set: State.SQLite.ClientDocumentTableDef.SetEventDefLike<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
Derived event definition for setting the value of the client document table.
If the document doesn't exist yet, the first .set event will create it.
set,}
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoDeleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}>(_eventDefRecord: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events, { 'v1.TodoCreated': ({ id: string
id, text: string
text }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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 id: string; readonly text?: string; readonly completed?: boolean; readonly deletedAt?: Date | null;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ id: string
id, text?: string
text, completed?: boolean
completed: false }), 'v1.TodoCompleted': ({ id: string
id }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoUncompleted': ({ id: string
id }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: false }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoDeleted': ({ id: string
id, deletedAt: Date
deletedAt }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoClearedCompleted': ({ deletedAt: Date
deletedAt }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: 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({ completed?: boolean | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: boolean;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly boolean[];} | undefined
completed: true }),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoDeleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}>(inputSchema: { events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events, state: InternalState
state })Configure the store
Section titled “Configure the store”Create a store.ts file in the src/livestore folder. This file configures the store adapter and exports a custom hook that components will use to access the store.
The useStore() hook accepts store configuration options (schema, adapter, store ID) and returns a store instance. It suspends while the store is loading, so make sure to use a Suspense boundary to handle the loading state.
import { function unstable_batchedUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
React Native also implements unstable_batchedUpdates
unstable_batchedUpdates as function batchUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
React Native also implements unstable_batchedUpdates
batchUpdates } from 'react-native'
import { const makePersistedAdapter: (options?: MakeDbOptions) => Adapter
Creates a persisted LiveStore adapter for Expo/React Native applications.
This adapter stores data in SQLite databases on the device filesystem, providing
persistence across app restarts. It supports optional sync backends for multi-device
synchronization.
Requirements:
- React Native New Architecture (Fabric) must be enabled
- Expo SDK 51+ recommended
makePersistedAdapter } from '@livestore/adapter-expo'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 { const makeWsSync: (options: WsSyncOptions) => SyncBackendConstructor<SyncMetadata>
Creates a sync backend that uses WebSocket to communicate with the sync backend.
makeWsSync } from '@livestore/sync-cf/client'
import { import events
events, import schema
schema, import tables
tables } from './schema.ts'
const const syncUrl: "https://example.org/sync"
syncUrl = 'https://example.org/sync'
const const adapter: Adapter
adapter = function makePersistedAdapter(options?: MakeDbOptions): Adapter
Creates a persisted LiveStore adapter for Expo/React Native applications.
This adapter stores data in SQLite databases on the device filesystem, providing
persistence across app restarts. It supports optional sync backends for multi-device
synchronization.
Requirements:
- React Native New Architecture (Fabric) must be enabled
- Expo SDK 51+ recommended
makePersistedAdapter({ sync?: SyncOptions
sync: { backend?: SyncBackendConstructor<any, JsonValue>
backend: function makeWsSync(options: WsSyncOptions): SyncBackendConstructor<SyncMetadata>
Creates a sync backend that uses WebSocket to communicate with the sync backend.
makeWsSync({ WsSyncOptions.url: string
URL of the sync backend
The protocol can either http/https or ws/wss
url: const syncUrl: "https://example.org/sync"
syncUrl }) },})
export const const useAppStore: () => Store<any, {}> & ReactApi
useAppStore = () => 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: 'expo-todomvc', 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, CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.batchUpdates?: (run: () => void) => void
Needed in React so LiveStore can apply multiple events in a single render.
batchUpdates, CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.boot?: (store: Store<any, {}>, ctx: { migrationsReport: MigrationsReport; parentSpan: Span;}) => SyncOrPromiseOrEffect<void, unknown, OtelTracer | LiveStoreContextRunning>
boot: (store: Store<any, {}>
store) => { if (store: Store<any, {}>
store.Store<any, {}>.query: <unknown>(query: Queryable<unknown> | { query: string; bindValues: Bindable; schema?: Decoder<unknown, never>;}, options?: { otelContext?: Context; debugRefreshReason?: RefreshReason;}) => unknown
Synchronously queries the database without creating a LiveQuery.
This is useful for queries that don't need to be reactive.
Example: Query builder
const completedTodos = store.query(tables.todo.where({ complete: true }))
Example: Raw SQL query
const completedTodos = store.query({ query: 'SELECT * FROM todo WHERE complete = 1', bindValues: {} })
query(import tables
tables.any
todos.any
count()) === 0) { store: Store<any, {}>
store.Store<any, {}>.commit: <readonly [any]>(list_0: any) => void (+3 overloads)
commit(import events
events.any
todoCreated({ id: `${string}-${string}-${string}-${string}-${string}`
id: var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}` (+2 overloads)
randomUUID(), text: string
text: 'Make coffee' })) } }, })import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, type SessionIdSymbol = typeof SessionIdSymbolconst SessionIdSymbol: typeof SessionIdSymbol
Can be used in queries to refer to the current session id.
Will be replaced with the actual session id at runtime.
In client document table:
const uiState = State.SQLite.clientDocument({ name: 'ui_state', schema: Schema.Struct({ theme: Schema.Literals(['dark', 'light', 'system']), user: Schema.String, showToolbar: Schema.Boolean, }), default: { value: defaultFrontendState, id: SessionIdSymbol },})
Or in a client document query:
const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
SessionIdSymbol, import State
State } from '@livestore/livestore'
export const const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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 id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: <string, string, false, "", false, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: ""; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text({ default?: ""
default: '' }), 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 }), 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 safe integer number of milliseconds since the Unix epoch is decoded as a
Date.
Encoding:
A Date is encoded as its millisecond timestamp.
Gotchas
JavaScript Date supports a narrower range than safe integers, so integers
outside the supported Date range fail decoding.
DateFromMillis }), }, }), uiState: State.SQLite.ClientDocumentTableDef<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiState: import State
State.import SQLite
SQLite.clientDocument<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly name: "uiState"; readonly schema: Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>; }>; readonly default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>({ name, schema: valueSchema, ...inputOptions }: { name: "uiState"; schema: Schema.Codec<{ readonly newTodoText: string; readonly filter: "completed" | ... 1 more ... | "active"; }, { ...; }, never, never>;} & { readonly name: "uiState"; readonly schema: Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>; }>; readonly default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; }; };}): State.SQLite.ClientDocumentTableDef<...>export clientDocument
Special:
- Synced across client sessions (e.g. tabs) but not across different clients
- Derived setters
- Emits client-only events
- Has implicit setter-materializers
- Similar to
React.useState (except it's persisted)
Careful:
- When changing the table definitions in a non-backwards compatible way, the state might be lost without
explicit materializers to handle the old auto-generated events
Usage:
// Querying data// `'some-id'` can be ommited for SessionIdSymbolstore.queryDb(clientDocumentTable.get('some-id'))
// Setting data// Again, `'some-id'` can be ommited for SessionIdSymbolstore.commit(clientDocumentTable.set({ someField: 'some-value' }, 'some-id'))
clientDocument({ name: "uiState"
name: 'uiState', schema: Schema.Codec<{ readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, never, never> & Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>
schema: import Schema
Schema.function Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>(fields: { readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}): Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>
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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ newTodoText: Schema.String
newTodoText: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, filter: Schema.Literals<readonly ["all", "active", "completed"]>
filter: import Schema
Schema.function Literals<readonly ["all", "active", "completed"]>(literals: readonly ["all", "active", "completed"]): Schema.Literals<readonly ["all", "active", "completed"]>
Creates a union schema from an array of literal values.
Example (Defining status codes)
import { Schema } from "effect"
const schema = Schema.Literals(["active", "inactive", "pending"])Schema.decodeSync(schema)("active") // => "active"
Literals(['all', 'active', 'completed']) }), default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; };}
default: { id: typeof SessionIdSymbol
id: const SessionIdSymbol: typeof SessionIdSymbol
Can be used in queries to refer to the current session id.
Will be replaced with the actual session id at runtime.
In client document table:
const uiState = State.SQLite.clientDocument({ name: 'ui_state', schema: Schema.Struct({ theme: Schema.Literals(['dark', 'light', 'system']), user: Schema.String, showToolbar: Schema.Boolean, }), default: { value: defaultFrontendState, id: SessionIdSymbol },})
Or in a client document query:
const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
SessionIdSymbol, value: { readonly newTodoText: ""; readonly filter: "all";}
value: { newTodoText: ""
newTodoText: '', filter: "all"
filter: 'all' } }, }),}
export const const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Codec<{ readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly text: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Codec<{ readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>(fields: { readonly id: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>
todoCompleted: import Events
Events.synced<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoCompleted"; schema: Schema.Codec<{ readonly id: string; }, { readonly id: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>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<{ readonly id: string;}, { readonly id: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String;}>(fields: { readonly id: Schema.String;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>
todoUncompleted: import Events
Events.synced<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoUncompleted"; schema: Schema.Codec<{ readonly id: string; }, { readonly id: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>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.TodoUncompleted"
name: 'v1.TodoUncompleted', schema: Schema.Codec<{ readonly id: string;}, { readonly id: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String;}>(fields: { readonly id: Schema.String;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>
todoDeleted: import Events
Events.synced<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>(args: { name: "v1.TodoDeleted"; schema: Schema.Codec<{ readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>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<{ readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}>(fields: { readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, 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 Date is encoded as an ISO string.
Invalid date strings fail decoding.
DateFromString, }), }), todoClearedCompleted: State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>
todoClearedCompleted: import Events
Events.synced<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>(args: { name: "v1.TodoClearedCompleted"; schema: Schema.Codec<{ readonly deletedAt: Date; }, { readonly deletedAt: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>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.TodoClearedCompleted"
name: 'v1.TodoClearedCompleted', schema: Schema.Codec<{ readonly deletedAt: Date;}, { readonly deletedAt: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly deletedAt: Schema.DateFromString;}>(fields: { readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ 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 Date is encoded as an ISO string.
Invalid date strings fail decoding.
DateFromString }), }), uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiStateSet: const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.uiState: State.SQLite.ClientDocumentTableDef<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiState.ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.Trait<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active"; }, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active"; }, { ...; }>.set: State.SQLite.ClientDocumentTableDef.SetEventDefLike<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
Derived event definition for setting the value of the client document table.
If the document doesn't exist yet, the first .set event will create it.
set,}
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoDeleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}>(_eventDefRecord: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events, { 'v1.TodoCreated': ({ id: string
id, text: string
text }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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 id: string; readonly text?: string; readonly completed?: boolean; readonly deletedAt?: Date | null;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ id: string
id, text?: string
text, completed?: boolean
completed: false }), 'v1.TodoCompleted': ({ id: string
id }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoUncompleted': ({ id: string
id }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: false }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoDeleted': ({ id: string
id, deletedAt: Date
deletedAt }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoClearedCompleted': ({ deletedAt: Date
deletedAt }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: 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({ completed?: boolean | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: boolean;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly boolean[];} | undefined
completed: true }),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoDeleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}>(inputSchema: { events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events, state: InternalState
state })Set up the store registry
Section titled “Set up the store registry”To enable store management throughout your app, create a StoreRegistry and provide it with a <StoreRegistryProvider>. The registry manages store instance lifecycles (loading, caching, disposal).
Wrap the provider in a Suspense boundary to handle the loading state for when the store is loading.
import { function StatusBar({ style, hideTransitionAnimation, translucent, backgroundColor: backgroundColorProp, ...props }: StatusBarProps): React.JSX.Element
A component that allows you to configure your status bar without directly calling imperative
methods like setBarStyle.
You will likely have multiple StatusBar components mounted in the same app at the same time.
For example, if you have multiple screens in your app, you may end up using one per screen.
The props of each StatusBar component will be merged in the order that they were mounted.
This component is built on top of the StatusBar
component exported from React Native, and it provides defaults that work better for Expo users.
StatusBar } from 'expo-status-bar'import { type type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC, const Suspense: ExoticComponent<SuspenseProps>
Lets you display a fallback until its children have finished loading.
Suspense, 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 { class SafeAreaView
SafeAreaView, class Text
Text, class View
View } from 'react-native'
/* oxlint-disable react/style-prop-object */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'
import { import ListTodos
ListTodos } from './components/ListTodos.tsx'import { import NewTodo
NewTodo } from './components/NewTodo.tsx'
const const suspenseFallback: JSX.Element
suspenseFallback = <class Text
Text>Loading LiveStore...</class Text
Text>const const appContentStyle: { flex: number; gap: number; padding: number;}
appContentStyle = { flex: number
flex: 1, gap: number
gap: 24, padding: number
padding: 24 }const const safeAreaStyle: { flex: number;}
safeAreaStyle = { flex: number
flex: 1 }
const const AppContent: FC
AppContent: type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC = () => ( <class View
View style?: StyleProp<ViewStyle>
style={const appContentStyle: { flex: number; gap: number; padding: number;}
appContentStyle}> <import NewTodo
NewTodo /> <import ListTodos
ListTodos /> </class View
View>)
export const const Root: FC
Root: type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC = () => { 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())
return ( <class SafeAreaView
SafeAreaView style?: StyleProp<ViewStyle>
style={const safeAreaStyle: { flex: number;}
safeAreaStyle}> <const Suspense: ExoticComponent<SuspenseProps>
Lets you display a fallback until its children have finished loading.
Suspense SuspenseProps.fallback?: ReactNode
A fallback react tree to show when a Suspense child (like React.lazy) suspends
fallback={const suspenseFallback: JSX.Element
suspenseFallback}> <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}> <const AppContent: FC
AppContent /> </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> </const Suspense: ExoticComponent<SuspenseProps>
Lets you display a fallback until its children have finished loading.
Suspense> <function StatusBar({ style, hideTransitionAnimation, translucent, backgroundColor: backgroundColorProp, ...props }: StatusBarProps): React.JSX.Element
A component that allows you to configure your status bar without directly calling imperative
methods like setBarStyle.
You will likely have multiple StatusBar components mounted in the same app at the same time.
For example, if you have multiple screens in your app, you may end up using one per screen.
The props of each StatusBar component will be merged in the order that they were mounted.
This component is built on top of the StatusBar
component exported from React Native, and it provides defaults that work better for Expo users.
StatusBar style?: StatusBarStyle
Sets the color of the status bar text. Default value is "auto" which
picks the appropriate value according to the active color scheme, eg:
if your app is dark mode, the style will be "light".
style="auto" /> </class SafeAreaView
SafeAreaView> )}import { type type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC, 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 type { (alias) interface TextStyleimport TextStyle
TextStyle, (alias) interface ViewStyleimport ViewStyle
ViewStyle } from 'react-native'import { class Button
Button, class ScrollView
ScrollView, class Text
Text, class View
View } from 'react-native'
import { import visibleTodos$
visibleTodos$ } from '../livestore/queries.ts'import { import events
events, type import tables
tables } from '../livestore/schema.ts'import { import useAppStore
useAppStore } from '../livestore/store.ts'
const const listContainerStyle: { flex: number; gap: number;}
listContainerStyle = { FlexStyle.flex?: number | undefined
flex: 1, FlexStyle.gap?: string | number | undefined
gap: 16 } satisfies (alias) interface ViewStyleimport ViewStyle
ViewStyleconst const listContentContainerStyle: { gap: number;}
listContentContainerStyle = { FlexStyle.gap?: string | number | undefined
gap: 12 } satisfies (alias) interface ViewStyleimport ViewStyle
ViewStyleconst const todoContainerStyle: { borderRadius: number; borderColor: string; borderWidth: number; padding: number; gap: number;}
todoContainerStyle = { ViewStyle.borderRadius?: string | AnimatableNumericValue | undefined
borderRadius: 12, ViewStyle.borderColor?: ColorValue | undefined
borderColor: '#d4d4d8', FlexStyle.borderWidth?: number | undefined
borderWidth: 1, FlexStyle.padding?: DimensionValue | undefined
padding: 16, FlexStyle.gap?: string | number | undefined
gap: 8,} satisfies (alias) interface ViewStyleimport ViewStyle
ViewStyleconst const todoTitleStyle: { fontSize: number; fontWeight: "600";}
todoTitleStyle = { TextStyle.fontSize?: number | undefined
fontSize: 16, TextStyle.fontWeight?: "600" | "normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "700" | "800" | "900" | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | "ultralight" | "thin" | "light" | "medium" | "regular" | "semibold" | "condensedBold" | "condensed" | "heavy" | "black" | undefined
Specifies font weight. The values 'normal' and 'bold' are supported
for most fonts. Not all fonts have a variant for each of the numeric
values, in that case the closest one is chosen.
fontWeight: '600' } satisfies (alias) interface TextStyleimport TextStyle
TextStyleconst const todoActionRowStyle: { flexDirection: "row"; gap: number;}
todoActionRowStyle = { FlexStyle.flexDirection?: "row" | "column" | "row-reverse" | "column-reverse" | undefined
flexDirection: 'row', FlexStyle.gap?: string | number | undefined
gap: 12 } satisfies (alias) interface ViewStyleimport ViewStyle
ViewStyle
export const const ListTodos: FC
ListTodos: type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC = () => { const const store: any
store = import useAppStore
useAppStore() const const todos: any
todos = const store: any
store.any
useQuery(import visibleTodos$
visibleTodos$)
const const toggleTodo: ({ id, completed }: typeof tables.todos.Type) => void
toggleTodo = useCallback<({ id, completed }: typeof tables.todos.Type) => void>(callback: ({ id, completed }: typeof tables.todos.Type) => void, deps: DependencyList): ({ id, completed }: typeof tables.todos.Type) => void
useCallback will return a memoized version of the callback that only changes if one of the inputs
has changed.
useCallback( ({ id: any
id, completed: any
completed }: typeof import tables
tables.any
todos.any
Type) => { const store: any
store.any
commit(completed: any
completed === true ? import events
events.any
todoUncompleted({ id: any
id }) : import events
events.any
todoCompleted({ id: any
id })) }, [const store: any
store], )
const const clearCompleted: () => void
clearCompleted = 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 store: any
store.any
commit(import events
events.any
todoClearedCompleted({ deletedAt: Date
deletedAt: new var Date: DateConstructornew () => Date (+3 overloads)
Date() })) }, [const store: any
store])
return ( <class View
View style?: StyleProp<ViewStyle>
style={const listContainerStyle: { flex: number; gap: number;}
listContainerStyle}> <class ScrollView
ScrollView contentContainerStyle?: StyleProp<ViewStyle>
These styles will be applied to the scroll view content container which
wraps all of the child views. Example:
return (
);
...
const styles = StyleSheet.create({
contentContainer: {
paddingVertical: 20
}
});
contentContainerStyle={const listContentContainerStyle: { gap: number;}
listContentContainerStyle}> {const todos: any
todos.any
map((todo: any
todo) => ( <const TodoItem: FC<{ todo: typeof tables.todos.Type; onToggle: (todo: typeof tables.todos.Type) => void;}>
TodoItem Attributes.key?: Key | null | undefined
key={todo: any
todo.any
id} todo: any
todo={todo: any
todo} onToggle: (todo: typeof tables.todos.Type) => void
onToggle={const toggleTodo: ({ id, completed }: typeof tables.todos.Type) => void
toggleTodo} /> ))} </class ScrollView
ScrollView> <class Button
Button title: string
Text to display inside the button. On Android the given title will be converted to the uppercased form.
title="Clear completed" onPress?: ((event: GestureResponderEvent) => void) | undefined
Called when the touch is released,
but not if cancelled (e.g. by a scroll that steals the responder lock).
onPress={const clearCompleted: () => void
clearCompleted} /> </class View
View> )}
const const TodoItem: FC<{ todo: typeof tables.todos.Type; onToggle: (todo: typeof tables.todos.Type) => void;}>
TodoItem: type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC<{ todo: any
todo: typeof import tables
tables.any
todos.any
Type onToggle: (todo: typeof tables.todos.Type) => void
onToggle: (todo: any
todo: typeof import tables
tables.any
todos.any
Type) => void}> = ({ todo: any
todo, onToggle: (todo: typeof tables.todos.Type) => void
onToggle }) => { const const store: any
store = import useAppStore
useAppStore() const const onTogglePress: () => void
onTogglePress = 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(() => onToggle: (todo: typeof tables.todos.Type) => void
onToggle(todo: any
todo), [onToggle: (todo: typeof tables.todos.Type) => void
onToggle, todo: any
todo]) const const onDeletePress: () => void
onDeletePress = 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 store: any
store.any
commit(import events
events.any
todoDeleted({ id: any
id: todo: any
todo.any
id, deletedAt: Date
deletedAt: new var Date: DateConstructornew () => Date (+3 overloads)
Date() })) }, [const store: any
store, todo: any
todo.any
id])
return ( <class View
View style?: StyleProp<ViewStyle>
style={const todoContainerStyle: { borderRadius: number; borderColor: string; borderWidth: number; padding: number; gap: number;}
todoContainerStyle}> <class Text
Text style?: StyleProp<TextStyle>
style={const todoTitleStyle: { fontSize: number; fontWeight: "600";}
todoTitleStyle}>{todo: any
todo.any
text}</class Text
Text> <class Text
Text>{todo: any
todo.any
completed === true ? 'Completed' : 'Pending'}</class Text
Text> <class View
View style?: StyleProp<ViewStyle>
style={const todoActionRowStyle: { flexDirection: "row"; gap: number;}
todoActionRowStyle}> <class Button
Button title: string
Text to display inside the button. On Android the given title will be converted to the uppercased form.
title={todo: any
todo.any
completed === true ? 'Mark pending' : 'Mark done'} onPress?: ((event: GestureResponderEvent) => void) | undefined
Called when the touch is released,
but not if cancelled (e.g. by a scroll that steals the responder lock).
onPress={const onTogglePress: () => void
onTogglePress} /> <class Button
Button title: string
Text to display inside the button. On Android the given title will be converted to the uppercased form.
title="Delete" onPress?: ((event: GestureResponderEvent) => void) | undefined
Called when the touch is released,
but not if cancelled (e.g. by a scroll that steals the responder lock).
onPress={const onDeletePress: () => void
onDeletePress} /> </class View
View> </class View
View> )}import { type type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC, 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 { class Button
Button, class TextInput
TextInput, class View
View } from 'react-native'
import { import uiState$
uiState$ } from '../livestore/queries.ts'import { import events
events } from '../livestore/schema.ts'import { import useAppStore
useAppStore } from '../livestore/store.ts'
const const formContainerStyle: { gap: number;}
formContainerStyle = { gap: number
gap: 12 }
export const const NewTodo: FC
NewTodo: type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC = () => { const const store: any
store = import useAppStore
useAppStore() const { const newTodoText: any
newTodoText } = const store: any
store.any
useQuery(import uiState$
uiState$)
const const updateText: (text: string) => void
updateText = 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 store: any
store.any
commit(import events
events.any
uiStateSet({ newTodoText: string
newTodoText: text: string
text })) }, [const store: any
store], ) const const createTodo: () => void
createTodo = 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 store: any
store.any
commit( import events
events.any
todoCreated({ id: `${string}-${string}-${string}-${string}-${string}`
id: var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}` (+2 overloads)
randomUUID(), text: any
text: const newTodoText: any
newTodoText }), import events
events.any
uiStateSet({ newTodoText: string
newTodoText: '' }), ) }, [const newTodoText: any
newTodoText, const store: any
store])
const const addSampleTodos: () => void
addSampleTodos = 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 const todos: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}[]
todos = var Array: ArrayConstructor
Array.ArrayConstructor.from<unknown, { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}>(iterable: Iterable<unknown> | ArrayLike<unknown>, mapfn: (v: unknown, k: number) => { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}, thisArg?: any): { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}[] (+3 overloads)
Creates an array from an iterable object.
from({ ArrayLike<T>.length: number
length: 5 }, (_: unknown
_, index: number
index) => ({ id: `${string}-${string}-${string}-${string}-${string}`
id: var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}` (+2 overloads)
randomUUID(), text: string
text: `Todo ${index: number
index + 1}`, })) const store: any
store.any
commit(...const todos: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}[]
todos.Array<{ id: `${string}-${string}-${string}-${string}-${string}`; text: string; }>.map<any>(callbackfn: (value: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}, index: number, array: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}[]) => any, thisArg?: any): any[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
map((todo: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}
todo) => import events
events.any
todoCreated(todo: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}
todo))) }, [const store: any
store])
return ( <class View
View style?: StyleProp<ViewStyle>
style={const formContainerStyle: { gap: number;}
formContainerStyle}> <class TextInput
TextInput value?: string | undefined
The value to show for the text input. TextInput is a controlled component,
which means the native value will be forced to match this value prop if provided.
For most uses this works great, but in some cases this may cause flickering - one common cause is preventing edits by keeping value the same.
In addition to simply setting the same value, either set editable={false},
or set/update maxLength to prevent unwanted edits without flicker.
value={const newTodoText: any
newTodoText} onChangeText?: ((text: string) => void) | undefined
Callback that is called when the text input's text changes.
Changed text is passed as an argument to the callback handler.
onChangeText={const updateText: (text: string) => void
updateText} placeholder?: string | undefined
The string that will be rendered before text input has been entered
placeholder="What needs to be done?" /> <class Button
Button title: string
Text to display inside the button. On Android the given title will be converted to the uppercased form.
title="Add todo" onPress?: ((event: GestureResponderEvent) => void) | undefined
Called when the touch is released,
but not if cancelled (e.g. by a scroll that steals the responder lock).
onPress={const createTodo: () => void
createTodo} /> <class Button
Button title: string
Text to display inside the button. On Android the given title will be converted to the uppercased form.
title="Add sample todos" onPress?: ((event: GestureResponderEvent) => void) | undefined
Called when the touch is released,
but not if cancelled (e.g. by a scroll that steals the responder lock).
onPress={const addSampleTodos: () => void
addSampleTodos} /> </class View
View> )}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 { import tables
tables } from './schema.ts'
export const const uiState$: LiveQueryDef<unknown, "def">
uiState$ = 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 tables
tables.any
uiState.any
get(), { label?: string
Used for debugging / devtools
label: 'uiState' })
export const const visibleTodos$: LiveQueryDef<unknown, "def">
visibleTodos$ = queryDb<unknown, unknown>(queryInput: ((get: GetAtomResult) => QueryInputRaw<unknown, readonly any[]>) | ((get: GetAtomResult) => 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( (get: GetAtomResult
get) => { const { const filter: any
filter } = get: <unknown>(atom: LiveQueryDef<unknown, "def"> | LiveQuery<unknown> | ISignal<unknown> | SignalDef<unknown> | Atom<unknown, any, RefreshReason>, otelContext?: Context, debugRefreshReason?: RefreshReason) => unknown
get(const uiState$: LiveQueryDef<unknown, "def">
uiState$)
return import tables
tables.any
todos.any
where({ deletedAt: null
deletedAt: null, completed: boolean | undefined
completed: const filter: any
filter === 'all' ? var undefined
undefined : const filter: any
filter === 'completed', }) }, { label?: string
Used for debugging / devtools
label: 'visibleTodos' },)import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, type SessionIdSymbol = typeof SessionIdSymbolconst SessionIdSymbol: typeof SessionIdSymbol
Can be used in queries to refer to the current session id.
Will be replaced with the actual session id at runtime.
In client document table:
const uiState = State.SQLite.clientDocument({ name: 'ui_state', schema: Schema.Struct({ theme: Schema.Literals(['dark', 'light', 'system']), user: Schema.String, showToolbar: Schema.Boolean, }), default: { value: defaultFrontendState, id: SessionIdSymbol },})
Or in a client document query:
const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
SessionIdSymbol, import State
State } from '@livestore/livestore'
export const const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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 id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: <string, string, false, "", false, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: ""; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text({ default?: ""
default: '' }), 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 }), 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 safe integer number of milliseconds since the Unix epoch is decoded as a
Date.
Encoding:
A Date is encoded as its millisecond timestamp.
Gotchas
JavaScript Date supports a narrower range than safe integers, so integers
outside the supported Date range fail decoding.
DateFromMillis }), }, }), uiState: State.SQLite.ClientDocumentTableDef<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiState: import State
State.import SQLite
SQLite.clientDocument<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly name: "uiState"; readonly schema: Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>; }>; readonly default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>({ name, schema: valueSchema, ...inputOptions }: { name: "uiState"; schema: Schema.Codec<{ readonly newTodoText: string; readonly filter: "completed" | ... 1 more ... | "active"; }, { ...; }, never, never>;} & { readonly name: "uiState"; readonly schema: Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>; }>; readonly default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; }; };}): State.SQLite.ClientDocumentTableDef<...>export clientDocument
Special:
- Synced across client sessions (e.g. tabs) but not across different clients
- Derived setters
- Emits client-only events
- Has implicit setter-materializers
- Similar to
React.useState (except it's persisted)
Careful:
- When changing the table definitions in a non-backwards compatible way, the state might be lost without
explicit materializers to handle the old auto-generated events
Usage:
// Querying data// `'some-id'` can be ommited for SessionIdSymbolstore.queryDb(clientDocumentTable.get('some-id'))
// Setting data// Again, `'some-id'` can be ommited for SessionIdSymbolstore.commit(clientDocumentTable.set({ someField: 'some-value' }, 'some-id'))
clientDocument({ name: "uiState"
name: 'uiState', schema: Schema.Codec<{ readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, never, never> & Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>
schema: import Schema
Schema.function Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>(fields: { readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}): Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>
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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ newTodoText: Schema.String
newTodoText: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, filter: Schema.Literals<readonly ["all", "active", "completed"]>
filter: import Schema
Schema.function Literals<readonly ["all", "active", "completed"]>(literals: readonly ["all", "active", "completed"]): Schema.Literals<readonly ["all", "active", "completed"]>
Creates a union schema from an array of literal values.
Example (Defining status codes)
import { Schema } from "effect"
const schema = Schema.Literals(["active", "inactive", "pending"])Schema.decodeSync(schema)("active") // => "active"
Literals(['all', 'active', 'completed']) }), default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; };}
default: { id: typeof SessionIdSymbol
id: const SessionIdSymbol: typeof SessionIdSymbol
Can be used in queries to refer to the current session id.
Will be replaced with the actual session id at runtime.
In client document table:
const uiState = State.SQLite.clientDocument({ name: 'ui_state', schema: Schema.Struct({ theme: Schema.Literals(['dark', 'light', 'system']), user: Schema.String, showToolbar: Schema.Boolean, }), default: { value: defaultFrontendState, id: SessionIdSymbol },})
Or in a client document query:
const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
SessionIdSymbol, value: { readonly newTodoText: ""; readonly filter: "all";}
value: { newTodoText: ""
newTodoText: '', filter: "all"
filter: 'all' } }, }),}
export const const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Codec<{ readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly text: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Codec<{ readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>(fields: { readonly id: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>
todoCompleted: import Events
Events.synced<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoCompleted"; schema: Schema.Codec<{ readonly id: string; }, { readonly id: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>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<{ readonly id: string;}, { readonly id: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String;}>(fields: { readonly id: Schema.String;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>
todoUncompleted: import Events
Events.synced<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoUncompleted"; schema: Schema.Codec<{ readonly id: string; }, { readonly id: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>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.TodoUncompleted"
name: 'v1.TodoUncompleted', schema: Schema.Codec<{ readonly id: string;}, { readonly id: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String;}>(fields: { readonly id: Schema.String;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>
todoDeleted: import Events
Events.synced<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>(args: { name: "v1.TodoDeleted"; schema: Schema.Codec<{ readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>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<{ readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}>(fields: { readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, 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 Date is encoded as an ISO string.
Invalid date strings fail decoding.
DateFromString, }), }), todoClearedCompleted: State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>
todoClearedCompleted: import Events
Events.synced<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>(args: { name: "v1.TodoClearedCompleted"; schema: Schema.Codec<{ readonly deletedAt: Date; }, { readonly deletedAt: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>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.TodoClearedCompleted"
name: 'v1.TodoClearedCompleted', schema: Schema.Codec<{ readonly deletedAt: Date;}, { readonly deletedAt: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly deletedAt: Schema.DateFromString;}>(fields: { readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ 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 Date is encoded as an ISO string.
Invalid date strings fail decoding.
DateFromString }), }), uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiStateSet: const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.uiState: State.SQLite.ClientDocumentTableDef<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiState.ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.Trait<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active"; }, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active"; }, { ...; }>.set: State.SQLite.ClientDocumentTableDef.SetEventDefLike<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
Derived event definition for setting the value of the client document table.
If the document doesn't exist yet, the first .set event will create it.
set,}
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoDeleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}>(_eventDefRecord: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events, { 'v1.TodoCreated': ({ id: string
id, text: string
text }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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 id: string; readonly text?: string; readonly completed?: boolean; readonly deletedAt?: Date | null;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ id: string
id, text?: string
text, completed?: boolean
completed: false }), 'v1.TodoCompleted': ({ id: string
id }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoUncompleted': ({ id: string
id }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: false }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoDeleted': ({ id: string
id, deletedAt: Date
deletedAt }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoClearedCompleted': ({ deletedAt: Date
deletedAt }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: 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({ completed?: boolean | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: boolean;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly boolean[];} | undefined
completed: true }),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoDeleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}>(inputSchema: { events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events, state: InternalState
state })import { function unstable_batchedUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
React Native also implements unstable_batchedUpdates
unstable_batchedUpdates as function batchUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
React Native also implements unstable_batchedUpdates
batchUpdates } from 'react-native'
import { const makePersistedAdapter: (options?: MakeDbOptions) => Adapter
Creates a persisted LiveStore adapter for Expo/React Native applications.
This adapter stores data in SQLite databases on the device filesystem, providing
persistence across app restarts. It supports optional sync backends for multi-device
synchronization.
Requirements:
- React Native New Architecture (Fabric) must be enabled
- Expo SDK 51+ recommended
makePersistedAdapter } from '@livestore/adapter-expo'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 { const makeWsSync: (options: WsSyncOptions) => SyncBackendConstructor<SyncMetadata>
Creates a sync backend that uses WebSocket to communicate with the sync backend.
makeWsSync } from '@livestore/sync-cf/client'
import { import events
events, import schema
schema, import tables
tables } from './schema.ts'
const const syncUrl: "https://example.org/sync"
syncUrl = 'https://example.org/sync'
const const adapter: Adapter
adapter = function makePersistedAdapter(options?: MakeDbOptions): Adapter
Creates a persisted LiveStore adapter for Expo/React Native applications.
This adapter stores data in SQLite databases on the device filesystem, providing
persistence across app restarts. It supports optional sync backends for multi-device
synchronization.
Requirements:
- React Native New Architecture (Fabric) must be enabled
- Expo SDK 51+ recommended
makePersistedAdapter({ sync?: SyncOptions
sync: { backend?: SyncBackendConstructor<any, JsonValue>
backend: function makeWsSync(options: WsSyncOptions): SyncBackendConstructor<SyncMetadata>
Creates a sync backend that uses WebSocket to communicate with the sync backend.
makeWsSync({ WsSyncOptions.url: string
URL of the sync backend
The protocol can either http/https or ws/wss
url: const syncUrl: "https://example.org/sync"
syncUrl }) },})
export const const useAppStore: () => Store<any, {}> & ReactApi
useAppStore = () => 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: 'expo-todomvc', 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, CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.batchUpdates?: (run: () => void) => void
Needed in React so LiveStore can apply multiple events in a single render.
batchUpdates, CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.boot?: (store: Store<any, {}>, ctx: { migrationsReport: MigrationsReport; parentSpan: Span;}) => SyncOrPromiseOrEffect<void, unknown, OtelTracer | LiveStoreContextRunning>
boot: (store: Store<any, {}>
store) => { if (store: Store<any, {}>
store.Store<any, {}>.query: <unknown>(query: Queryable<unknown> | { query: string; bindValues: Bindable; schema?: Decoder<unknown, never>;}, options?: { otelContext?: Context; debugRefreshReason?: RefreshReason;}) => unknown
Synchronously queries the database without creating a LiveQuery.
This is useful for queries that don't need to be reactive.
Example: Query builder
const completedTodos = store.query(tables.todo.where({ complete: true }))
Example: Raw SQL query
const completedTodos = store.query({ query: 'SELECT * FROM todo WHERE complete = 1', bindValues: {} })
query(import tables
tables.any
todos.any
count()) === 0) { store: Store<any, {}>
store.Store<any, {}>.commit: <readonly [any]>(list_0: any) => void (+3 overloads)
commit(import events
events.any
todoCreated({ id: `${string}-${string}-${string}-${string}-${string}`
id: var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}` (+2 overloads)
randomUUID(), text: string
text: 'Make coffee' })) } }, })Commit events
Section titled “Commit events”After setting up the registry, use the useAppStore() hook from any component to access the store and commit events.
import { type type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC, 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 { class Button
Button, class TextInput
TextInput, class View
View } from 'react-native'
import { import uiState$
uiState$ } from '../livestore/queries.ts'import { import events
events } from '../livestore/schema.ts'import { import useAppStore
useAppStore } from '../livestore/store.ts'
const const formContainerStyle: { gap: number;}
formContainerStyle = { gap: number
gap: 12 }
export const const NewTodo: FC
NewTodo: type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC = () => { const const store: any
store = import useAppStore
useAppStore() const { const newTodoText: any
newTodoText } = const store: any
store.any
useQuery(import uiState$
uiState$)
const const updateText: (text: string) => void
updateText = 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 store: any
store.any
commit(import events
events.any
uiStateSet({ newTodoText: string
newTodoText: text: string
text })) }, [const store: any
store], ) const const createTodo: () => void
createTodo = 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 store: any
store.any
commit( import events
events.any
todoCreated({ id: `${string}-${string}-${string}-${string}-${string}`
id: var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}` (+2 overloads)
randomUUID(), text: any
text: const newTodoText: any
newTodoText }), import events
events.any
uiStateSet({ newTodoText: string
newTodoText: '' }), ) }, [const newTodoText: any
newTodoText, const store: any
store])
const const addSampleTodos: () => void
addSampleTodos = 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 const todos: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}[]
todos = var Array: ArrayConstructor
Array.ArrayConstructor.from<unknown, { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}>(iterable: Iterable<unknown> | ArrayLike<unknown>, mapfn: (v: unknown, k: number) => { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}, thisArg?: any): { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}[] (+3 overloads)
Creates an array from an iterable object.
from({ ArrayLike<T>.length: number
length: 5 }, (_: unknown
_, index: number
index) => ({ id: `${string}-${string}-${string}-${string}-${string}`
id: var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}` (+2 overloads)
randomUUID(), text: string
text: `Todo ${index: number
index + 1}`, })) const store: any
store.any
commit(...const todos: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}[]
todos.Array<{ id: `${string}-${string}-${string}-${string}-${string}`; text: string; }>.map<any>(callbackfn: (value: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}, index: number, array: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}[]) => any, thisArg?: any): any[]
Calls a defined callback function on each element of an array, and returns an array that contains the results.
map((todo: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}
todo) => import events
events.any
todoCreated(todo: { id: `${string}-${string}-${string}-${string}-${string}`; text: string;}
todo))) }, [const store: any
store])
return ( <class View
View style?: StyleProp<ViewStyle>
style={const formContainerStyle: { gap: number;}
formContainerStyle}> <class TextInput
TextInput value?: string | undefined
The value to show for the text input. TextInput is a controlled component,
which means the native value will be forced to match this value prop if provided.
For most uses this works great, but in some cases this may cause flickering - one common cause is preventing edits by keeping value the same.
In addition to simply setting the same value, either set editable={false},
or set/update maxLength to prevent unwanted edits without flicker.
value={const newTodoText: any
newTodoText} onChangeText?: ((text: string) => void) | undefined
Callback that is called when the text input's text changes.
Changed text is passed as an argument to the callback handler.
onChangeText={const updateText: (text: string) => void
updateText} placeholder?: string | undefined
The string that will be rendered before text input has been entered
placeholder="What needs to be done?" /> <class Button
Button title: string
Text to display inside the button. On Android the given title will be converted to the uppercased form.
title="Add todo" onPress?: ((event: GestureResponderEvent) => void) | undefined
Called when the touch is released,
but not if cancelled (e.g. by a scroll that steals the responder lock).
onPress={const createTodo: () => void
createTodo} /> <class Button
Button title: string
Text to display inside the button. On Android the given title will be converted to the uppercased form.
title="Add sample todos" onPress?: ((event: GestureResponderEvent) => void) | undefined
Called when the touch is released,
but not if cancelled (e.g. by a scroll that steals the responder lock).
onPress={const addSampleTodos: () => void
addSampleTodos} /> </class View
View> )}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 { import tables
tables } from './schema.ts'
export const const uiState$: LiveQueryDef<unknown, "def">
uiState$ = 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 tables
tables.any
uiState.any
get(), { label?: string
Used for debugging / devtools
label: 'uiState' })
export const const visibleTodos$: LiveQueryDef<unknown, "def">
visibleTodos$ = queryDb<unknown, unknown>(queryInput: ((get: GetAtomResult) => QueryInputRaw<unknown, readonly any[]>) | ((get: GetAtomResult) => 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( (get: GetAtomResult
get) => { const { const filter: any
filter } = get: <unknown>(atom: LiveQueryDef<unknown, "def"> | LiveQuery<unknown> | ISignal<unknown> | SignalDef<unknown> | Atom<unknown, any, RefreshReason>, otelContext?: Context, debugRefreshReason?: RefreshReason) => unknown
get(const uiState$: LiveQueryDef<unknown, "def">
uiState$)
return import tables
tables.any
todos.any
where({ deletedAt: null
deletedAt: null, completed: boolean | undefined
completed: const filter: any
filter === 'all' ? var undefined
undefined : const filter: any
filter === 'completed', }) }, { label?: string
Used for debugging / devtools
label: 'visibleTodos' },)import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, type SessionIdSymbol = typeof SessionIdSymbolconst SessionIdSymbol: typeof SessionIdSymbol
Can be used in queries to refer to the current session id.
Will be replaced with the actual session id at runtime.
In client document table:
const uiState = State.SQLite.clientDocument({ name: 'ui_state', schema: Schema.Struct({ theme: Schema.Literals(['dark', 'light', 'system']), user: Schema.String, showToolbar: Schema.Boolean, }), default: { value: defaultFrontendState, id: SessionIdSymbol },})
Or in a client document query:
const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
SessionIdSymbol, import State
State } from '@livestore/livestore'
export const const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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 id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: <string, string, false, "", false, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: ""; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text({ default?: ""
default: '' }), 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 }), 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 safe integer number of milliseconds since the Unix epoch is decoded as a
Date.
Encoding:
A Date is encoded as its millisecond timestamp.
Gotchas
JavaScript Date supports a narrower range than safe integers, so integers
outside the supported Date range fail decoding.
DateFromMillis }), }, }), uiState: State.SQLite.ClientDocumentTableDef<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiState: import State
State.import SQLite
SQLite.clientDocument<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly name: "uiState"; readonly schema: Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>; }>; readonly default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>({ name, schema: valueSchema, ...inputOptions }: { name: "uiState"; schema: Schema.Codec<{ readonly newTodoText: string; readonly filter: "completed" | ... 1 more ... | "active"; }, { ...; }, never, never>;} & { readonly name: "uiState"; readonly schema: Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>; }>; readonly default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; }; };}): State.SQLite.ClientDocumentTableDef<...>export clientDocument
Special:
- Synced across client sessions (e.g. tabs) but not across different clients
- Derived setters
- Emits client-only events
- Has implicit setter-materializers
- Similar to
React.useState (except it's persisted)
Careful:
- When changing the table definitions in a non-backwards compatible way, the state might be lost without
explicit materializers to handle the old auto-generated events
Usage:
// Querying data// `'some-id'` can be ommited for SessionIdSymbolstore.queryDb(clientDocumentTable.get('some-id'))
// Setting data// Again, `'some-id'` can be ommited for SessionIdSymbolstore.commit(clientDocumentTable.set({ someField: 'some-value' }, 'some-id'))
clientDocument({ name: "uiState"
name: 'uiState', schema: Schema.Codec<{ readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, never, never> & Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>
schema: import Schema
Schema.function Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>(fields: { readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}): Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>
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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ newTodoText: Schema.String
newTodoText: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, filter: Schema.Literals<readonly ["all", "active", "completed"]>
filter: import Schema
Schema.function Literals<readonly ["all", "active", "completed"]>(literals: readonly ["all", "active", "completed"]): Schema.Literals<readonly ["all", "active", "completed"]>
Creates a union schema from an array of literal values.
Example (Defining status codes)
import { Schema } from "effect"
const schema = Schema.Literals(["active", "inactive", "pending"])Schema.decodeSync(schema)("active") // => "active"
Literals(['all', 'active', 'completed']) }), default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; };}
default: { id: typeof SessionIdSymbol
id: const SessionIdSymbol: typeof SessionIdSymbol
Can be used in queries to refer to the current session id.
Will be replaced with the actual session id at runtime.
In client document table:
const uiState = State.SQLite.clientDocument({ name: 'ui_state', schema: Schema.Struct({ theme: Schema.Literals(['dark', 'light', 'system']), user: Schema.String, showToolbar: Schema.Boolean, }), default: { value: defaultFrontendState, id: SessionIdSymbol },})
Or in a client document query:
const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
SessionIdSymbol, value: { readonly newTodoText: ""; readonly filter: "all";}
value: { newTodoText: ""
newTodoText: '', filter: "all"
filter: 'all' } }, }),}
export const const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Codec<{ readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly text: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Codec<{ readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>(fields: { readonly id: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>
todoCompleted: import Events
Events.synced<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoCompleted"; schema: Schema.Codec<{ readonly id: string; }, { readonly id: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>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<{ readonly id: string;}, { readonly id: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String;}>(fields: { readonly id: Schema.String;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>
todoUncompleted: import Events
Events.synced<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoUncompleted"; schema: Schema.Codec<{ readonly id: string; }, { readonly id: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>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.TodoUncompleted"
name: 'v1.TodoUncompleted', schema: Schema.Codec<{ readonly id: string;}, { readonly id: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String;}>(fields: { readonly id: Schema.String;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>
todoDeleted: import Events
Events.synced<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>(args: { name: "v1.TodoDeleted"; schema: Schema.Codec<{ readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>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<{ readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}>(fields: { readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, 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 Date is encoded as an ISO string.
Invalid date strings fail decoding.
DateFromString, }), }), todoClearedCompleted: State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>
todoClearedCompleted: import Events
Events.synced<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>(args: { name: "v1.TodoClearedCompleted"; schema: Schema.Codec<{ readonly deletedAt: Date; }, { readonly deletedAt: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>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.TodoClearedCompleted"
name: 'v1.TodoClearedCompleted', schema: Schema.Codec<{ readonly deletedAt: Date;}, { readonly deletedAt: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly deletedAt: Schema.DateFromString;}>(fields: { readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ 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 Date is encoded as an ISO string.
Invalid date strings fail decoding.
DateFromString }), }), uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiStateSet: const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.uiState: State.SQLite.ClientDocumentTableDef<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiState.ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.Trait<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active"; }, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active"; }, { ...; }>.set: State.SQLite.ClientDocumentTableDef.SetEventDefLike<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
Derived event definition for setting the value of the client document table.
If the document doesn't exist yet, the first .set event will create it.
set,}
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoDeleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}>(_eventDefRecord: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events, { 'v1.TodoCreated': ({ id: string
id, text: string
text }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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 id: string; readonly text?: string; readonly completed?: boolean; readonly deletedAt?: Date | null;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ id: string
id, text?: string
text, completed?: boolean
completed: false }), 'v1.TodoCompleted': ({ id: string
id }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoUncompleted': ({ id: string
id }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: false }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoDeleted': ({ id: string
id, deletedAt: Date
deletedAt }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoClearedCompleted': ({ deletedAt: Date
deletedAt }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: 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({ completed?: boolean | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: boolean;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly boolean[];} | undefined
completed: true }),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoDeleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}>(inputSchema: { events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events, state: InternalState
state })import { function unstable_batchedUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
React Native also implements unstable_batchedUpdates
unstable_batchedUpdates as function batchUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
React Native also implements unstable_batchedUpdates
batchUpdates } from 'react-native'
import { const makePersistedAdapter: (options?: MakeDbOptions) => Adapter
Creates a persisted LiveStore adapter for Expo/React Native applications.
This adapter stores data in SQLite databases on the device filesystem, providing
persistence across app restarts. It supports optional sync backends for multi-device
synchronization.
Requirements:
- React Native New Architecture (Fabric) must be enabled
- Expo SDK 51+ recommended
makePersistedAdapter } from '@livestore/adapter-expo'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 { const makeWsSync: (options: WsSyncOptions) => SyncBackendConstructor<SyncMetadata>
Creates a sync backend that uses WebSocket to communicate with the sync backend.
makeWsSync } from '@livestore/sync-cf/client'
import { import events
events, import schema
schema, import tables
tables } from './schema.ts'
const const syncUrl: "https://example.org/sync"
syncUrl = 'https://example.org/sync'
const const adapter: Adapter
adapter = function makePersistedAdapter(options?: MakeDbOptions): Adapter
Creates a persisted LiveStore adapter for Expo/React Native applications.
This adapter stores data in SQLite databases on the device filesystem, providing
persistence across app restarts. It supports optional sync backends for multi-device
synchronization.
Requirements:
- React Native New Architecture (Fabric) must be enabled
- Expo SDK 51+ recommended
makePersistedAdapter({ sync?: SyncOptions
sync: { backend?: SyncBackendConstructor<any, JsonValue>
backend: function makeWsSync(options: WsSyncOptions): SyncBackendConstructor<SyncMetadata>
Creates a sync backend that uses WebSocket to communicate with the sync backend.
makeWsSync({ WsSyncOptions.url: string
URL of the sync backend
The protocol can either http/https or ws/wss
url: const syncUrl: "https://example.org/sync"
syncUrl }) },})
export const const useAppStore: () => Store<any, {}> & ReactApi
useAppStore = () => 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: 'expo-todomvc', 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, CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.batchUpdates?: (run: () => void) => void
Needed in React so LiveStore can apply multiple events in a single render.
batchUpdates, CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.boot?: (store: Store<any, {}>, ctx: { migrationsReport: MigrationsReport; parentSpan: Span;}) => SyncOrPromiseOrEffect<void, unknown, OtelTracer | LiveStoreContextRunning>
boot: (store: Store<any, {}>
store) => { if (store: Store<any, {}>
store.Store<any, {}>.query: <unknown>(query: Queryable<unknown> | { query: string; bindValues: Bindable; schema?: Decoder<unknown, never>;}, options?: { otelContext?: Context; debugRefreshReason?: RefreshReason;}) => unknown
Synchronously queries the database without creating a LiveQuery.
This is useful for queries that don't need to be reactive.
Example: Query builder
const completedTodos = store.query(tables.todo.where({ complete: true }))
Example: Raw SQL query
const completedTodos = store.query({ query: 'SELECT * FROM todo WHERE complete = 1', bindValues: {} })
query(import tables
tables.any
todos.any
count()) === 0) { store: Store<any, {}>
store.Store<any, {}>.commit: <readonly [any]>(list_0: any) => void (+3 overloads)
commit(import events
events.any
todoCreated({ id: `${string}-${string}-${string}-${string}-${string}`
id: var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}` (+2 overloads)
randomUUID(), text: string
text: 'Make coffee' })) } }, })Queries
Section titled “Queries”To retrieve data from the database, define a query using queryDb from @livestore/livestore, then execute it with store.useQuery().
Consider abstracting queries into a separate file to keep your code organized, though you can also define them directly within components if preferred.
import { type type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC, 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 type { (alias) interface TextStyleimport TextStyle
TextStyle, (alias) interface ViewStyleimport ViewStyle
ViewStyle } from 'react-native'import { class Button
Button, class ScrollView
ScrollView, class Text
Text, class View
View } from 'react-native'
import { import visibleTodos$
visibleTodos$ } from '../livestore/queries.ts'import { import events
events, type import tables
tables } from '../livestore/schema.ts'import { import useAppStore
useAppStore } from '../livestore/store.ts'
const const listContainerStyle: { flex: number; gap: number;}
listContainerStyle = { FlexStyle.flex?: number | undefined
flex: 1, FlexStyle.gap?: string | number | undefined
gap: 16 } satisfies (alias) interface ViewStyleimport ViewStyle
ViewStyleconst const listContentContainerStyle: { gap: number;}
listContentContainerStyle = { FlexStyle.gap?: string | number | undefined
gap: 12 } satisfies (alias) interface ViewStyleimport ViewStyle
ViewStyleconst const todoContainerStyle: { borderRadius: number; borderColor: string; borderWidth: number; padding: number; gap: number;}
todoContainerStyle = { ViewStyle.borderRadius?: string | AnimatableNumericValue | undefined
borderRadius: 12, ViewStyle.borderColor?: ColorValue | undefined
borderColor: '#d4d4d8', FlexStyle.borderWidth?: number | undefined
borderWidth: 1, FlexStyle.padding?: DimensionValue | undefined
padding: 16, FlexStyle.gap?: string | number | undefined
gap: 8,} satisfies (alias) interface ViewStyleimport ViewStyle
ViewStyleconst const todoTitleStyle: { fontSize: number; fontWeight: "600";}
todoTitleStyle = { TextStyle.fontSize?: number | undefined
fontSize: 16, TextStyle.fontWeight?: "600" | "normal" | "bold" | "100" | "200" | "300" | "400" | "500" | "700" | "800" | "900" | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | "ultralight" | "thin" | "light" | "medium" | "regular" | "semibold" | "condensedBold" | "condensed" | "heavy" | "black" | undefined
Specifies font weight. The values 'normal' and 'bold' are supported
for most fonts. Not all fonts have a variant for each of the numeric
values, in that case the closest one is chosen.
fontWeight: '600' } satisfies (alias) interface TextStyleimport TextStyle
TextStyleconst const todoActionRowStyle: { flexDirection: "row"; gap: number;}
todoActionRowStyle = { FlexStyle.flexDirection?: "row" | "column" | "row-reverse" | "column-reverse" | undefined
flexDirection: 'row', FlexStyle.gap?: string | number | undefined
gap: 12 } satisfies (alias) interface ViewStyleimport ViewStyle
ViewStyle
export const const ListTodos: FC
ListTodos: type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC = () => { const const store: any
store = import useAppStore
useAppStore() const const todos: any
todos = const store: any
store.any
useQuery(import visibleTodos$
visibleTodos$)
const const toggleTodo: ({ id, completed }: typeof tables.todos.Type) => void
toggleTodo = useCallback<({ id, completed }: typeof tables.todos.Type) => void>(callback: ({ id, completed }: typeof tables.todos.Type) => void, deps: DependencyList): ({ id, completed }: typeof tables.todos.Type) => void
useCallback will return a memoized version of the callback that only changes if one of the inputs
has changed.
useCallback( ({ id: any
id, completed: any
completed }: typeof import tables
tables.any
todos.any
Type) => { const store: any
store.any
commit(completed: any
completed === true ? import events
events.any
todoUncompleted({ id: any
id }) : import events
events.any
todoCompleted({ id: any
id })) }, [const store: any
store], )
const const clearCompleted: () => void
clearCompleted = 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 store: any
store.any
commit(import events
events.any
todoClearedCompleted({ deletedAt: Date
deletedAt: new var Date: DateConstructornew () => Date (+3 overloads)
Date() })) }, [const store: any
store])
return ( <class View
View style?: StyleProp<ViewStyle>
style={const listContainerStyle: { flex: number; gap: number;}
listContainerStyle}> <class ScrollView
ScrollView contentContainerStyle?: StyleProp<ViewStyle>
These styles will be applied to the scroll view content container which
wraps all of the child views. Example:
return (
);
...
const styles = StyleSheet.create({
contentContainer: {
paddingVertical: 20
}
});
contentContainerStyle={const listContentContainerStyle: { gap: number;}
listContentContainerStyle}> {const todos: any
todos.any
map((todo: any
todo) => ( <const TodoItem: FC<{ todo: typeof tables.todos.Type; onToggle: (todo: typeof tables.todos.Type) => void;}>
TodoItem Attributes.key?: Key | null | undefined
key={todo: any
todo.any
id} todo: any
todo={todo: any
todo} onToggle: (todo: typeof tables.todos.Type) => void
onToggle={const toggleTodo: ({ id, completed }: typeof tables.todos.Type) => void
toggleTodo} /> ))} </class ScrollView
ScrollView> <class Button
Button title: string
Text to display inside the button. On Android the given title will be converted to the uppercased form.
title="Clear completed" onPress?: ((event: GestureResponderEvent) => void) | undefined
Called when the touch is released,
but not if cancelled (e.g. by a scroll that steals the responder lock).
onPress={const clearCompleted: () => void
clearCompleted} /> </class View
View> )}
const const TodoItem: FC<{ todo: typeof tables.todos.Type; onToggle: (todo: typeof tables.todos.Type) => void;}>
TodoItem: type FC<P = {}> = FunctionComponent<P>
Represents the type of a function component. Can optionally
receive a type argument that represents the props the component
receives.
FC<{ todo: any
todo: typeof import tables
tables.any
todos.any
Type onToggle: (todo: typeof tables.todos.Type) => void
onToggle: (todo: any
todo: typeof import tables
tables.any
todos.any
Type) => void}> = ({ todo: any
todo, onToggle: (todo: typeof tables.todos.Type) => void
onToggle }) => { const const store: any
store = import useAppStore
useAppStore() const const onTogglePress: () => void
onTogglePress = 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(() => onToggle: (todo: typeof tables.todos.Type) => void
onToggle(todo: any
todo), [onToggle: (todo: typeof tables.todos.Type) => void
onToggle, todo: any
todo]) const const onDeletePress: () => void
onDeletePress = 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 store: any
store.any
commit(import events
events.any
todoDeleted({ id: any
id: todo: any
todo.any
id, deletedAt: Date
deletedAt: new var Date: DateConstructornew () => Date (+3 overloads)
Date() })) }, [const store: any
store, todo: any
todo.any
id])
return ( <class View
View style?: StyleProp<ViewStyle>
style={const todoContainerStyle: { borderRadius: number; borderColor: string; borderWidth: number; padding: number; gap: number;}
todoContainerStyle}> <class Text
Text style?: StyleProp<TextStyle>
style={const todoTitleStyle: { fontSize: number; fontWeight: "600";}
todoTitleStyle}>{todo: any
todo.any
text}</class Text
Text> <class Text
Text>{todo: any
todo.any
completed === true ? 'Completed' : 'Pending'}</class Text
Text> <class View
View style?: StyleProp<ViewStyle>
style={const todoActionRowStyle: { flexDirection: "row"; gap: number;}
todoActionRowStyle}> <class Button
Button title: string
Text to display inside the button. On Android the given title will be converted to the uppercased form.
title={todo: any
todo.any
completed === true ? 'Mark pending' : 'Mark done'} onPress?: ((event: GestureResponderEvent) => void) | undefined
Called when the touch is released,
but not if cancelled (e.g. by a scroll that steals the responder lock).
onPress={const onTogglePress: () => void
onTogglePress} /> <class Button
Button title: string
Text to display inside the button. On Android the given title will be converted to the uppercased form.
title="Delete" onPress?: ((event: GestureResponderEvent) => void) | undefined
Called when the touch is released,
but not if cancelled (e.g. by a scroll that steals the responder lock).
onPress={const onDeletePress: () => void
onDeletePress} /> </class View
View> </class View
View> )}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 { import tables
tables } from './schema.ts'
export const const uiState$: LiveQueryDef<unknown, "def">
uiState$ = 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 tables
tables.any
uiState.any
get(), { label?: string
Used for debugging / devtools
label: 'uiState' })
export const const visibleTodos$: LiveQueryDef<unknown, "def">
visibleTodos$ = queryDb<unknown, unknown>(queryInput: ((get: GetAtomResult) => QueryInputRaw<unknown, readonly any[]>) | ((get: GetAtomResult) => 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( (get: GetAtomResult
get) => { const { const filter: any
filter } = get: <unknown>(atom: LiveQueryDef<unknown, "def"> | LiveQuery<unknown> | ISignal<unknown> | SignalDef<unknown> | Atom<unknown, any, RefreshReason>, otelContext?: Context, debugRefreshReason?: RefreshReason) => unknown
get(const uiState$: LiveQueryDef<unknown, "def">
uiState$)
return import tables
tables.any
todos.any
where({ deletedAt: null
deletedAt: null, completed: boolean | undefined
completed: const filter: any
filter === 'all' ? var undefined
undefined : const filter: any
filter === 'completed', }) }, { label?: string
Used for debugging / devtools
label: 'visibleTodos' },)import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, type SessionIdSymbol = typeof SessionIdSymbolconst SessionIdSymbol: typeof SessionIdSymbol
Can be used in queries to refer to the current session id.
Will be replaced with the actual session id at runtime.
In client document table:
const uiState = State.SQLite.clientDocument({ name: 'ui_state', schema: Schema.Struct({ theme: Schema.Literals(['dark', 'light', 'system']), user: Schema.String, showToolbar: Schema.Boolean, }), default: { value: defaultFrontendState, id: SessionIdSymbol },})
Or in a client document query:
const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
SessionIdSymbol, import State
State } from '@livestore/livestore'
export const const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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 id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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: { id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;}
id: import State
State.import SQLite
SQLite.const text: <string, string, false, typeof NoDefault, true, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;}
text: import State
State.import SQLite
SQLite.const text: <string, string, false, "", false, false>(args: { schema?: Schema.Codec<string, string, never, never>; default?: ""; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text({ default?: ""
default: '' }), 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 }), 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 safe integer number of milliseconds since the Unix epoch is decoded as a
Date.
Encoding:
A Date is encoded as its millisecond timestamp.
Gotchas
JavaScript Date supports a narrower range than safe integers, so integers
outside the supported Date range fail decoding.
DateFromMillis }), }, }), uiState: State.SQLite.ClientDocumentTableDef<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiState: import State
State.import SQLite
SQLite.clientDocument<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly name: "uiState"; readonly schema: Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>; }>; readonly default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>({ name, schema: valueSchema, ...inputOptions }: { name: "uiState"; schema: Schema.Codec<{ readonly newTodoText: string; readonly filter: "completed" | ... 1 more ... | "active"; }, { ...; }, never, never>;} & { readonly name: "uiState"; readonly schema: Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>; }>; readonly default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; }; };}): State.SQLite.ClientDocumentTableDef<...>export clientDocument
Special:
- Synced across client sessions (e.g. tabs) but not across different clients
- Derived setters
- Emits client-only events
- Has implicit setter-materializers
- Similar to
React.useState (except it's persisted)
Careful:
- When changing the table definitions in a non-backwards compatible way, the state might be lost without
explicit materializers to handle the old auto-generated events
Usage:
// Querying data// `'some-id'` can be ommited for SessionIdSymbolstore.queryDb(clientDocumentTable.get('some-id'))
// Setting data// Again, `'some-id'` can be ommited for SessionIdSymbolstore.commit(clientDocumentTable.set({ someField: 'some-value' }, 'some-id'))
clientDocument({ name: "uiState"
name: 'uiState', schema: Schema.Codec<{ readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, never, never> & Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>
schema: import Schema
Schema.function Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>(fields: { readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}): Schema.Struct<{ readonly newTodoText: Schema.String; readonly filter: Schema.Literals<readonly ["all", "active", "completed"]>;}>
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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ newTodoText: Schema.String
newTodoText: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, filter: Schema.Literals<readonly ["all", "active", "completed"]>
filter: import Schema
Schema.function Literals<readonly ["all", "active", "completed"]>(literals: readonly ["all", "active", "completed"]): Schema.Literals<readonly ["all", "active", "completed"]>
Creates a union schema from an array of literal values.
Example (Defining status codes)
import { Schema } from "effect"
const schema = Schema.Literals(["active", "inactive", "pending"])Schema.decodeSync(schema)("active") // => "active"
Literals(['all', 'active', 'completed']) }), default: { readonly id: typeof SessionIdSymbol; readonly value: { readonly newTodoText: ""; readonly filter: "all"; };}
default: { id: typeof SessionIdSymbol
id: const SessionIdSymbol: typeof SessionIdSymbol
Can be used in queries to refer to the current session id.
Will be replaced with the actual session id at runtime.
In client document table:
const uiState = State.SQLite.clientDocument({ name: 'ui_state', schema: Schema.Struct({ theme: Schema.Literals(['dark', 'light', 'system']), user: Schema.String, showToolbar: Schema.Boolean, }), default: { value: defaultFrontendState, id: SessionIdSymbol },})
Or in a client document query:
const query$ = queryDb(tables.uiState.get(SessionIdSymbol))
SessionIdSymbol, value: { readonly newTodoText: ""; readonly filter: "all";}
value: { newTodoText: ""
newTodoText: '', filter: "all"
filter: 'all' } }, }),}
export const const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Codec<{ readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly text: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Codec<{ readonly id: string; readonly text: string;}, { readonly id: string; readonly text: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>(fields: { readonly id: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>
todoCompleted: import Events
Events.synced<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoCompleted"; schema: Schema.Codec<{ readonly id: string; }, { readonly id: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>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<{ readonly id: string;}, { readonly id: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String;}>(fields: { readonly id: Schema.String;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>
todoUncompleted: import Events
Events.synced<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoUncompleted"; schema: Schema.Codec<{ readonly id: string; }, { readonly id: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>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.TodoUncompleted"
name: 'v1.TodoUncompleted', schema: Schema.Codec<{ readonly id: string;}, { readonly id: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String;}>(fields: { readonly id: Schema.String;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>
todoDeleted: import Events
Events.synced<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>(args: { name: "v1.TodoDeleted"; schema: Schema.Codec<{ readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>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<{ readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}>(fields: { readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ readonly id: 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, 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 Date is encoded as an ISO string.
Invalid date strings fail decoding.
DateFromString, }), }), todoClearedCompleted: State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>
todoClearedCompleted: import Events
Events.synced<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>(args: { name: "v1.TodoClearedCompleted"; schema: Schema.Codec<{ readonly deletedAt: Date; }, { readonly deletedAt: string; }, never, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>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.TodoClearedCompleted"
name: 'v1.TodoClearedCompleted', schema: Schema.Codec<{ readonly deletedAt: Date;}, { readonly deletedAt: string;}, never, never>
schema: import Schema
Schema.function Struct<{ readonly deletedAt: Schema.DateFromString;}>(fields: { readonly deletedAt: Schema.DateFromString;}): Schema.Struct<{ 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.
Declared fields may be inherited and are copied to own properties in the
output. The __proto__ field is accepted only when it is an own property.
Parsing does not guarantee that output keys retain their input order.
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
Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 }) // => { name: "Alice", age: 30 }
Struct({ 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 Date is encoded as an ISO string.
Invalid date strings fail decoding.
DateFromString }), }), uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiStateSet: const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.uiState: State.SQLite.ClientDocumentTableDef<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
uiState.ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.Trait<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active"; }, { readonly newTodoText: string; readonly filter: "completed" | "all" | "active"; }, { ...; }>.set: State.SQLite.ClientDocumentTableDef.SetEventDefLike<"uiState", { readonly newTodoText: string; readonly filter: "completed" | "all" | "active";}, { partialSet: true; default: { id: typeof SessionIdSymbol; value: { readonly newTodoText: ""; readonly filter: "all"; }; };}>
Derived event definition for setting the value of the client document table.
If the document doesn't exist yet, the first .set event will create it.
set,}
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoDeleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}>(_eventDefRecord: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events, { 'v1.TodoCreated': ({ id: string
id, text: string
text }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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 id: string; readonly text?: string; readonly completed?: boolean; readonly deletedAt?: Date | null;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ id: string
id, text?: string
text, completed?: boolean
completed: false }), 'v1.TodoCompleted': ({ id: string
id }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoUncompleted': ({ id: string
id }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: false }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoDeleted': ({ id: string
id, deletedAt: Date
deletedAt }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: 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({ id?: string | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: string;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[];} | undefined
id }), 'v1.TodoClearedCompleted': ({ deletedAt: Date
deletedAt }) => const tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<{ readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<...>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: 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({ completed?: boolean | { op: Exclude<QueryBuilder.WhereOps.SingleValue, QueryBuilder.WhereOps.JsonArray>; value: boolean;} | { op: QueryBuilder.WhereOps.MultiValue; value: readonly boolean[];} | undefined
completed: true }),})
const const state: InternalState
state = import State
State.import SQLite
SQLite.const makeState: <{ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}>(inputSchema: { tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Codec<string, string, never, never>; default: Some<"">; 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<...>>; uiState: State.SQLite.ClientDocumentTableDef<...>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>>; "v1.TodoDeleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}>(inputSchema: { events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }>; todoClearedCompleted: State.SQLite.EventDef<...>; uiStateSet: State.SQLite.ClientDocumentTableDef.SetEventDefLike<...>;}
events, state: InternalState
state })import { function unstable_batchedUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
React Native also implements unstable_batchedUpdates
unstable_batchedUpdates as function batchUpdates<A, R>(callback: (a: A) => R, a: A): R (+1 overload)
React Native also implements unstable_batchedUpdates
batchUpdates } from 'react-native'
import { const makePersistedAdapter: (options?: MakeDbOptions) => Adapter
Creates a persisted LiveStore adapter for Expo/React Native applications.
This adapter stores data in SQLite databases on the device filesystem, providing
persistence across app restarts. It supports optional sync backends for multi-device
synchronization.
Requirements:
- React Native New Architecture (Fabric) must be enabled
- Expo SDK 51+ recommended
makePersistedAdapter } from '@livestore/adapter-expo'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 { const makeWsSync: (options: WsSyncOptions) => SyncBackendConstructor<SyncMetadata>
Creates a sync backend that uses WebSocket to communicate with the sync backend.
makeWsSync } from '@livestore/sync-cf/client'
import { import events
events, import schema
schema, import tables
tables } from './schema.ts'
const const syncUrl: "https://example.org/sync"
syncUrl = 'https://example.org/sync'
const const adapter: Adapter
adapter = function makePersistedAdapter(options?: MakeDbOptions): Adapter
Creates a persisted LiveStore adapter for Expo/React Native applications.
This adapter stores data in SQLite databases on the device filesystem, providing
persistence across app restarts. It supports optional sync backends for multi-device
synchronization.
Requirements:
- React Native New Architecture (Fabric) must be enabled
- Expo SDK 51+ recommended
makePersistedAdapter({ sync?: SyncOptions
sync: { backend?: SyncBackendConstructor<any, JsonValue>
backend: function makeWsSync(options: WsSyncOptions): SyncBackendConstructor<SyncMetadata>
Creates a sync backend that uses WebSocket to communicate with the sync backend.
makeWsSync({ WsSyncOptions.url: string
URL of the sync backend
The protocol can either http/https or ws/wss
url: const syncUrl: "https://example.org/sync"
syncUrl }) },})
export const const useAppStore: () => Store<any, {}> & ReactApi
useAppStore = () => 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: 'expo-todomvc', 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, CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.batchUpdates?: (run: () => void) => void
Needed in React so LiveStore can apply multiple events in a single render.
batchUpdates, CreateStoreOptions<any, {}, Codec<Json, Json, never, never>>.boot?: (store: Store<any, {}>, ctx: { migrationsReport: MigrationsReport; parentSpan: Span;}) => SyncOrPromiseOrEffect<void, unknown, OtelTracer | LiveStoreContextRunning>
boot: (store: Store<any, {}>
store) => { if (store: Store<any, {}>
store.Store<any, {}>.query: <unknown>(query: Queryable<unknown> | { query: string; bindValues: Bindable; schema?: Decoder<unknown, never>;}, options?: { otelContext?: Context; debugRefreshReason?: RefreshReason;}) => unknown
Synchronously queries the database without creating a LiveQuery.
This is useful for queries that don't need to be reactive.
Example: Query builder
const completedTodos = store.query(tables.todo.where({ complete: true }))
Example: Raw SQL query
const completedTodos = store.query({ query: 'SELECT * FROM todo WHERE complete = 1', bindValues: {} })
query(import tables
tables.any
todos.any
count()) === 0) { store: Store<any, {}>
store.Store<any, {}>.commit: <readonly [any]>(list_0: any) => void (+3 overloads)
commit(import events
events.any
todoCreated({ id: `${string}-${string}-${string}-${string}-${string}`
id: var crypto: Crypto
crypto.Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}` (+2 overloads)
randomUUID(), text: string
text: 'Make coffee' })) } }, })Devtools
Section titled “Devtools”To open the devtools, run the app and from your terminal press shift + m, then select LiveStore Devtools and press Enter.

This will open the devtools in a new tab in your default browser.

Use the devtools to inspect the state of your LiveStore database, execute events, track performance, and more.
Database location
Section titled “Database location”With Expo Go
Section titled “With Expo Go”To open the database in Finder, run the following command in your terminal:
open $(find $(xcrun simctl get_app_container booted host.exp.Exponent data) -path "*/Documents/ExponentExperienceData/*livestore-expo*" -print -quit)/SQLiteWith development builds
Section titled “With development builds”For development builds, the app SQLite database is stored in the app’s Library directory.
Example:
/Users/<USERNAME>/Library/Developer/CoreSimulator/Devices/<DEVICE_ID>/data/Containers/Data/Application/<APP_ID>/Documents/SQLite/app.db
To open the database in Finder, run the following command in your terminal:
open $(xcrun simctl get_app_container booted [APP_BUNDLE_ID] data)/Documents/SQLiteReplace [APP_BUNDLE_ID] with your app’s bundle ID. e.g. dev.livestore.livestore-expo.
Further notes
Section titled “Further notes”- LiveStore doesn’t yet support Expo Web (see #130)