Cloudflare Durable Object adapter
The Cloudflare Durable Object adapter enables running LiveStore applications on Cloudflare Workers with stateful Durable Objects for synchronized real-time data.
Installation
Section titled “Installation”pnpm add @livestore/adapter-cloudflare @livestore/sync-cfConfiguration
Section titled “Configuration”Wrangler configuration
Section titled “Wrangler configuration”Configure your wrangler.toml with the required Durable Object bindings:
name = "my-livestore-app"main = "./src/worker.ts"compatibility_date = "2025-05-07"compatibility_flags = [ "enable_request_signal", # Required for HTTP RPC streams]
[[durable_objects.bindings]]name = "SYNC_BACKEND_DO"class_name = "SyncBackendDO"
[[durable_objects.bindings]]name = "CLIENT_DO"class_name = "LiveStoreClientDO"
[[migrations]]tag = "v1"new_sqlite_classes = ["SyncBackendDO", "LiveStoreClientDO"]
[[d1_databases]]binding = "DB"database_name = "my-livestore-db"database_id = "your-database-id"Environment types
Section titled “Environment types”Define your Worker bindings so TypeScript can guide you when wiring Durable Objects:
import type { (alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback } from '@livestore/adapter-cloudflare'import type { import CfTypes
CfTypes, (alias) interface SyncBackendRpcInterfaceimport SyncBackendRpcInterface
Durable Object interface supporting the DO RPC protocol for DO <> DO syncing.
SyncBackendRpcInterface } from '@livestore/sync-cf/cf-worker'
export type type Env = { CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>; DB: CfTypes.D1Database;}
Env = { type CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>
CLIENT_DO: import CfTypes
CfTypes.class DurableObjectNamespace<T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined>
DurableObjectNamespace<(alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback> type SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>
SYNC_BACKEND_DO: import CfTypes
CfTypes.class DurableObjectNamespace<T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined>
DurableObjectNamespace<(alias) interface SyncBackendRpcInterfaceimport SyncBackendRpcInterface
Durable Object interface supporting the DO RPC protocol for DO <> DO syncing.
SyncBackendRpcInterface> type DB: CfTypes.D1Database
DB: import CfTypes
CfTypes.class D1Database
D1Database}We also use a small helper to extract the store identifier from incoming requests:
Basic setup
Section titled “Basic setup”1. Create the sync backend Durable Object
Section titled “1. Create the sync backend Durable Object”The sync backend handles pushing and pulling events between clients:
import * as import SyncBackend
SyncBackend from '@livestore/sync-cf/cf-worker'
export class class SyncBackendDO
SyncBackendDO extends import SyncBackend
SyncBackend.const makeDurableObject: (options?: SyncBackend.MakeDurableObjectClassOptions) => { new (ctx: SyncBackend.DoState, env: SyncBackend.Env): SyncBackend.DoObject<SyncBackend.SyncBackendRpcInterface>;}
Creates a Durable Object class for handling WebSocket-based sync.
A sync Durable Object is uniquely scoped to a specific storeId.
The sync DO supports 3 transport modes:
- HTTP JSON-RPC
- WebSocket
- Durable Object RPC calls (only works in combination with
@livestore/adapter-cf)
Example:
// In your Cloudflare Worker fileimport { makeDurableObject } from '@livestore/sync-cf/cf-worker'
export class SyncBackendDO extends makeDurableObject({ onPush: async (message) => { console.log('onPush', message.batch) }, onPull: async (message) => { console.log('onPull', message) },}) {}
wrangler.toml
[[durable_objects.bindings]]name = "SYNC_BACKEND_DO"class_name = "SyncBackendDO"
[[migrations]]tag = "v1"new_sqlite_classes = ["SyncBackendDO"]
makeDurableObject({ // Optional: Handle push events // onPush: async (message, { storeId }) => { // console.log(`onPush for store (${storeId})`, message.batch) // },}) {}2. Create the client Durable Object
Section titled “2. Create the client Durable Object”Each client Durable Object hosts a LiveStore instance and exposes DO RPC callbacks:
import { class DurableObject<Env = Cloudflare.Env, Props = {}>
DurableObject } from 'cloudflare:workers'
import { type (alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback, const createStoreDoPromise: <TSchema extends LiveStoreSchema, TEnv, TState extends DurableObjectState = DurableObjectState<unknown>>(options: CreateStoreDoOptions<TSchema, TEnv, TState>) => Promise<Store<TSchema, {}>>
Promise-based wrapper around createStoreDo for simpler async/await usage.
Equivalent to calling createStoreDo(options).pipe(Effect.runPromise) with
logging configured automatically.
createStoreDoPromise } from '@livestore/adapter-cloudflare'import { function nanoid(size?: number): string
Generate secure URL-friendly unique ID.
By default, the ID will have 21 symbols to have a collision probability
similar to UUID v4.
import { nanoid } from 'nanoid'model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
nanoid, type class Store<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}>
Central interface to a LiveStore database providing reactive queries, event commits, and sync.
A Store instance wraps a local SQLite database that is kept in sync with other clients via
an event log. Instead of mutating state directly, you commit events that get materialized
into database rows. Queries automatically re-run when their underlying tables change.
Creating a Store
Use createStore (Effect-based) or createStorePromise to obtain a Store instance.
In React applications, use StoreRegistry with <StoreRegistryProvider> and the useStore() hook
which manages the Store lifecycle.
Querying Data
Use
Store.query
for one-shot reads or
Store.subscribe
for reactive subscriptions.
Both accept query builders (e.g. tables.todo.where({ complete: true })) or custom LiveQueryDefs.
Committing Events
Use
Store.commit
to persist events. Events are immediately materialized locally and
asynchronously synced to other clients. Multiple events can be committed atomically.
Lifecycle
The Store must be shut down when no longer needed via
Store.shutdown
or
Store.shutdownPromise
. Framework integrations (React, Effect) handle this automatically.
Store, type type Unsubscribe = () => void
Function returned by store.subscribe() to stop receiving updates.
Call this to unsubscribe from a query and release the associated resources.
Unsubscribe } from '@livestore/livestore'import { const handleSyncUpdateRpc: (ctx: DurableObjectState, payload: Uint8Array<ArrayBuffer>) => Promise<void>
Routes an update from the sync backend into this client's live pull.
Only ctx and payload go here; storeId is for reloading your store on a rebuilt DO (see example).
import { DurableObject } from 'cloudflare:workers'import { ClientDoWithRpcCallback } from '@livestore/common-cf'
export class MyDurableObject extends DurableObject implements ClientDoWithRpcCallback { // ...
async syncUpdateRpc(payload: Uint8Array<ArrayBuffer>, storeId: string) { await this.getStore(storeId) return handleSyncUpdateRpc(this.ctx, payload) }}
handleSyncUpdateRpc } from '@livestore/sync-cf/client'
import type { import Env
Env } from './env.ts'import { import schema
schema, import tables
tables } from './schema.ts'import { import storeIdFromRequest
storeIdFromRequest } from './shared.ts'
type type AlarmInfo = { isRetry: boolean; retryCount: number;}
AlarmInfo = { isRetry: boolean
isRetry: boolean retryCount: number
retryCount: number}
export class class LiveStoreClientDO
LiveStoreClientDO extends class DurableObject<Env = Cloudflare.Env, Props = {}>
DurableObject<import Env
Env> implements (alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback { override LiveStoreClientDO.__DURABLE_OBJECT_BRAND: never
__DURABLE_OBJECT_BRAND: never = var undefined
undefined as never
private LiveStoreClientDO.storeId: string | undefined
storeId: string | undefined private LiveStoreClientDO.cachedStore: Store<any, {}> | undefined
cachedStore: class Store<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}>
Central interface to a LiveStore database providing reactive queries, event commits, and sync.
A Store instance wraps a local SQLite database that is kept in sync with other clients via
an event log. Instead of mutating state directly, you commit events that get materialized
into database rows. Queries automatically re-run when their underlying tables change.
Creating a Store
Use createStore (Effect-based) or createStorePromise to obtain a Store instance.
In React applications, use StoreRegistry with <StoreRegistryProvider> and the useStore() hook
which manages the Store lifecycle.
Querying Data
Use
Store.query
for one-shot reads or
Store.subscribe
for reactive subscriptions.
Both accept query builders (e.g. tables.todo.where({ complete: true })) or custom LiveQueryDefs.
Committing Events
Use
Store.commit
to persist events. Events are immediately materialized locally and
asynchronously synced to other clients. Multiple events can be committed atomically.
Lifecycle
The Store must be shut down when no longer needed via
Store.shutdown
or
Store.shutdownPromise
. Framework integrations (React, Effect) handle this automatically.
Store<typeof import schema
schema> | undefined private LiveStoreClientDO.storeSubscription: Unsubscribe | undefined
storeSubscription: type Unsubscribe = () => void
Function returned by store.subscribe() to stop receiving updates.
Call this to unsubscribe from a query and release the associated resources.
Unsubscribe | undefined private readonly LiveStoreClientDO.todosQuery: any
todosQuery = import tables
tables.any
todos.any
select()
override async LiveStoreClientDO.fetch(request: Request): Promise<Response>
fetch(request: Request<unknown, CfProperties<unknown>>
request: interface Request<CfHostMetadata = unknown, Cf = CfProperties<CfHostMetadata>>
The Request interface of the Fetch API represents a resource request.
Request): interface Promise<T>
Represents the completion of an asynchronous operation
Promise<interface Response
The Response interface of the Fetch API represents the response to a request.
Response> { // @ts-expect-error TODO remove casts once CF types are fixed in https://github.com/cloudflare/workerd/issues/4811 this.LiveStoreClientDO.storeId: string | undefined
storeId = import storeIdFromRequest
storeIdFromRequest(request: Request<unknown, CfProperties<unknown>>
request)
const const store: Store<any, {}>
store = await this.LiveStoreClientDO.getStore(): Promise<Store<any, {}>>
getStore() await this.LiveStoreClientDO.subscribeToStore(): Promise<void>
subscribeToStore()
const const todos: unknown
todos = const 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(this.LiveStoreClientDO.todosQuery: any
todosQuery) return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response
The Response interface of the Fetch API represents the response to a request.
Response(var JSON: JSON
An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
JSON.JSON.stringify(value: any, replacer?: (number | string)[] | null, space?: string | number): string (+1 overload)
Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
stringify(const todos: unknown
todos, null, 2), { ResponseInit.headers?: HeadersInit
headers: { 'Content-Type': 'application/json' }, }) }
private async LiveStoreClientDO.getStore(): Promise<Store<any, {}>>
getStore() { if (this.LiveStoreClientDO.cachedStore: Store<any, {}> | undefined
cachedStore !== var undefined
undefined) { return this.LiveStoreClientDO.cachedStore: Store<any, {}>
cachedStore }
const const storeId: string
storeId = this.LiveStoreClientDO.storeId: string | undefined
storeId ?? function nanoid(size?: number): string
Generate secure URL-friendly unique ID.
By default, the ID will have 21 symbols to have a collision probability
similar to UUID v4.
import { nanoid } from 'nanoid'model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
nanoid()
const const store: Store<any, {}>
store = await createStoreDoPromise<any, Env, DurableObjectState<unknown>>(options: CreateStoreDoOptions<any, Env, DurableObjectState<unknown>>): Promise<Store<any, {}>>
Promise-based wrapper around createStoreDo for simpler async/await usage.
Equivalent to calling createStoreDo(options).pipe(Effect.runPromise) with
logging configured automatically.
createStoreDoPromise({ schema: any
LiveStore schema that defines state, migrations, and validators.
schema, storeId: string
Logical identifier for the store instance persisted inside the Durable Object.
storeId, clientId: string
Unique identifier for the client that owns the Durable Object instance.
clientId: 'client-do', sessionId: string
Identifier for the LiveStore session running inside the Durable Object.
sessionId: function nanoid(size?: number): string
Generate secure URL-friendly unique ID.
By default, the ID will have 21 symbols to have a collision probability
similar to UUID v4.
import { nanoid } from 'nanoid'model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
nanoid(), durableObject: { ctx: DurableObjectState<unknown>; env: Env; bindingName: any;}
Runtime details about the Durable Object this store runs inside. Needed for sync backend to call back to this instance.
durableObject: { // @ts-expect-error TODO remove once CF types are fixed in https://github.com/cloudflare/workerd/issues/4811 ctx: DurableObjectState<unknown>
Durable Object state handle (e.g. this.ctx).
ctx: this.CloudflareWorkersModule.DurableObject<Env, {}>.ctx: DurableObjectState<{}>
ctx, env: Env
Environment bindings associated with the Durable Object.
env: this.CloudflareWorkersModule.DurableObject<Env, {}>.env: Env
env, bindingName: any
Binding name Cloudflare uses to reach this Durable Object from other workers.
bindingName: 'CLIENT_DO', }, syncBackendStub: DurableObjectStub<SyncBackendRpcInterface>
RPC stub pointing at the sync backend Durable Object used for replication.
syncBackendStub: this.CloudflareWorkersModule.DurableObject<Env, {}>.env: Env
env.any
SYNC_BACKEND_DO.any
get(this.CloudflareWorkersModule.DurableObject<Env, {}>.env: Env
env.any
SYNC_BACKEND_DO.any
idFromName(const storeId: string
storeId)), livePull?: boolean
Enables live pull mode to receive sync updates via Durable Object RPC callbacks.
livePull: true, })
this.LiveStoreClientDO.cachedStore: Store<any, {}> | undefined
cachedStore = const store: Store<any, {}>
store return const store: Store<any, {}>
store }
private async LiveStoreClientDO.subscribeToStore(): Promise<void>
subscribeToStore() { const const store: Store<any, {}>
store = await this.LiveStoreClientDO.getStore(): Promise<Store<any, {}>>
getStore()
if (this.LiveStoreClientDO.storeSubscription: Unsubscribe | undefined
storeSubscription === var undefined
undefined) { this.LiveStoreClientDO.storeSubscription: Unsubscribe | undefined
storeSubscription = const store: Store<any, {}>
store.Store<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}>.subscribe: <readonly any[]>(query: Queryable<readonly any[]>, onUpdate: (value: readonly any[]) => void, options?: SubscribeOptions<readonly any[]> | undefined) => Unsubscribe (+1 overload)
subscribe(this.LiveStoreClientDO.todosQuery: any
todosQuery, (todos: readonly any[]
todos: interface ReadonlyArray<T>
ReadonlyArray<typeof import tables
tables.any
todos.any
Type>) => { var console: Console
console.Console.log(...data: any[]): void (+3 overloads)
The console.log() static method outputs a message to the console.
log(`todos for store (${this.LiveStoreClientDO.storeId: string | undefined
storeId})`, todos: readonly any[]
todos) }) }
await this.CloudflareWorkersModule.DurableObject<Env, {}>.ctx: DurableObjectState<{}>
ctx.DurableObjectState<{}>.storage: DurableObjectStorage
storage.DurableObjectStorage.setAlarm(scheduledTime: number | Date, options?: DurableObjectSetAlarmOptions): Promise<void>
setAlarm(var Date: DateConstructor
Enables basic storage and retrieval of dates and times.
Date.DateConstructor.now(): number
Returns the number of milliseconds elapsed since midnight, January 1, 1970 Universal Coordinated Time (UTC).
now() + 1000) }
override LiveStoreClientDO.alarm(_alarmInfo?: AlarmInfo): void | Promise<void>
alarm(_alarmInfo: AlarmInfo | undefined
_alarmInfo?: type AlarmInfo = { isRetry: boolean; retryCount: number;}
AlarmInfo): void | interface Promise<T>
Represents the completion of an asynchronous operation
Promise<void> { return this.LiveStoreClientDO.subscribeToStore(): Promise<void>
subscribeToStore() }
async LiveStoreClientDO.syncUpdateRpc(payload: Uint8Array<ArrayBuffer>, storeId: string): Promise<void>
The sync backend calls this to deliver a live update; storeId lets a rebuilt DO reload its
store before delivering. See the Cloudflare Durable Object adapter docs for the recovery options.
syncUpdateRpc(payload: Uint8Array<ArrayBuffer>
payload: interface Uint8Array<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike>
A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
requested number of bytes could not be allocated an exception is raised.
Uint8Array<interface ArrayBuffer
Represents a raw buffer of binary data, which is used to store data for the
different typed arrays. ArrayBuffers cannot be read from or written to directly,
but can be passed to a typed array or DataView Object to interpret the raw
buffer as needed.
ArrayBuffer>, storeId: string
storeId: string) { this.LiveStoreClientDO.storeId: string | undefined
storeId = storeId: string
storeId await this.LiveStoreClientDO.getStore(): Promise<Store<any, {}>>
getStore() // @ts-expect-error TODO remove once CF types are fixed in https://github.com/cloudflare/workerd/issues/4811 await function handleSyncUpdateRpc(ctx: DurableObjectState, payload: Uint8Array<ArrayBuffer>): Promise<void>
Routes an update from the sync backend into this client's live pull.
Only ctx and payload go here; storeId is for reloading your store on a rebuilt DO (see example).
import { DurableObject } from 'cloudflare:workers'import { ClientDoWithRpcCallback } from '@livestore/common-cf'
export class MyDurableObject extends DurableObject implements ClientDoWithRpcCallback { // ...
async syncUpdateRpc(payload: Uint8Array<ArrayBuffer>, storeId: string) { await this.getStore(storeId) return handleSyncUpdateRpc(this.ctx, payload) }}
handleSyncUpdateRpc(this.CloudflareWorkersModule.DurableObject<Env, {}>.ctx: DurableObjectState<{}>
ctx, payload: Uint8Array<ArrayBuffer>
payload) }}import type { (alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback } from '@livestore/adapter-cloudflare'import type { import CfTypes
CfTypes, (alias) interface SyncBackendRpcInterfaceimport SyncBackendRpcInterface
Durable Object interface supporting the DO RPC protocol for DO <> DO syncing.
SyncBackendRpcInterface } from '@livestore/sync-cf/cf-worker'
export type type Env = { CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>; DB: CfTypes.D1Database;}
Env = { type CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>
CLIENT_DO: import CfTypes
CfTypes.class DurableObjectNamespace<T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined>
DurableObjectNamespace<(alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback> type SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>
SYNC_BACKEND_DO: import CfTypes
CfTypes.class DurableObjectNamespace<T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined>
DurableObjectNamespace<(alias) interface SyncBackendRpcInterfaceimport SyncBackendRpcInterface
Durable Object interface supporting the DO RPC protocol for DO <> DO syncing.
SyncBackendRpcInterface> type DB: CfTypes.D1Database
DB: import CfTypes
CfTypes.class D1Database
D1Database}import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, 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<...>>;}
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 number of milliseconds since the Unix epoch is decoded as a Date.
Encoding:
A Date is encoded as its millisecond timestamp.
Gotchas
This schema accepts any number, including NaN, Infinity, and -Infinity.
Those values decode to invalid Date instances.
DateFromMillis }), }, }),}
export const const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoCreated: import Events
Events.synced<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">>(args: { name: "v1.TodoCreated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">, never, never>;} & Omit<...>): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>(fields: { readonly id: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">>
todoCompleted: import Events
Events.synced<"v1.TodoCompleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">>(args: { name: "v1.TodoCompleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, false>, "derived" | "clientOnly">): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCompleted"
name: 'v1.TodoCompleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">, 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.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">>
todoUncompleted: import Events
Events.synced<"v1.TodoUncompleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">>(args: { name: "v1.TodoUncompleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, false>, "derived" | "clientOnly">): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoUncompleted"
name: 'v1.TodoUncompleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">, 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.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>
todoDeleted: import Events
Events.synced<"v1.TodoDeleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>(args: { name: "v1.TodoDeleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString; }, "Encoded">, never, never>;} & Omit<...>): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoDeleted"
name: 'v1.TodoDeleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">, 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.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, deletedAt: Schema.DateFromString
deletedAt: import Schema
Schema.const DateFromString: Schema.DateFromString
Type-level representation of
DateFromString
.
Schema that decodes a string into a JavaScript Date.
When to use
Use to model string-encoded dates that decode to JavaScript Date objects
and encode back to strings.
Details
Decoding:
The string is passed to JavaScript Date construction.
Encoding:
A valid Date is encoded as an ISO string; an invalid Date is encoded as
"Invalid Date".
Gotchas
Invalid date strings can decode to invalid Date instances.
DateFromString.Bottom<unknown, unknown, unknown, unknown, Declaration, decodeTo<Date, String, never, never>, unknown, unknown, readonly [], unknown, "readonly", "required", "no-default", "readonly", "required">.check(checks_0: Check<Date>, ...checks: Check<Date>[]): Schema.DateFromString
check(import Schema
Schema.function isDateValid(annotations?: Schema.Annotations.Filter): Filter<globalThis.Date>
Validates that a Date object represents a valid date (not an invalid date
like new Date("invalid")).
Details
JSON Schema:
This check does not have a direct JSON Schema equivalent, as JSON Schema
validates date strings, not Date objects.
Arbitrary:
When generating test data with fast-check, this applies a valid: true
constraint to ensure generated Date objects are valid.
isDateValid()), }), }), todoClearedCompleted: State.SQLite.EventDef<"v1.TodoClearedCompleted", Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Encoded">>
todoClearedCompleted: import Events
Events.synced<"v1.TodoClearedCompleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Encoded">>(args: { name: "v1.TodoClearedCompleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString; }, "Type">, Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString; }, "Encoded">, never, never>;} & Omit<...>): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoClearedCompleted"
name: 'v1.TodoClearedCompleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Encoded">, 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.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ deletedAt: Schema.DateFromString
deletedAt: import Schema
Schema.const DateFromString: Schema.DateFromString
Type-level representation of
DateFromString
.
Schema that decodes a string into a JavaScript Date.
When to use
Use to model string-encoded dates that decode to JavaScript Date objects
and encode back to strings.
Details
Decoding:
The string is passed to JavaScript Date construction.
Encoding:
A valid Date is encoded as an ISO string; an invalid Date is encoded as
"Invalid Date".
Gotchas
Invalid date strings can decode to invalid Date instances.
DateFromString.Bottom<unknown, unknown, unknown, unknown, Declaration, decodeTo<Date, String, never, never>, unknown, unknown, readonly [], unknown, "readonly", "required", "no-default", "readonly", "required">.check(checks_0: Check<Date>, ...checks: Check<Date>[]): Schema.DateFromString
check(import Schema
Schema.function isDateValid(annotations?: Schema.Annotations.Filter): Filter<globalThis.Date>
Validates that a Date object represents a valid date (not an invalid date
like new Date("invalid")).
Details
JSON Schema:
This check does not have a direct JSON Schema equivalent, as JSON Schema
validates date strings, not Date objects.
Arbitrary:
When generating test data with fast-check, this applies a valid: true
constraint to ensure generated Date objects are valid.
isDateValid()) }), }),}
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>>; "v1.TodoUncompleted": State.SQLite.Materializer<...>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>;}>(_eventDefRecord: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>;}
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<...>>;}
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 Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { ...;}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ id: string
id, text?: string
text, completed?: boolean
completed: 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<...>>;}
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<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly 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<...>>;}
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<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: 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<...>>;}
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<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly 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<...>>;}
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<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly 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<...>>; }; 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<...>>; }; 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<...>>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>>; "v1.TodoUncompleted": State.SQLite.Materializer<...>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}>(inputSchema: { events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>;}
events, state: InternalState
state })import type { import CfTypes
CfTypes } from '@livestore/sync-cf/cf-worker'
export const const storeIdFromRequest: (request: CfTypes.Request) => string
storeIdFromRequest = (request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request: import CfTypes
CfTypes.interface Request<CfHostMetadata = unknown, Cf = CfTypes.CfProperties<CfHostMetadata>>
The Request interface of the Fetch API represents a resource request.
Request) => { const const url: URL
url = new var URL: new (url: string | URL, base?: string | URL) => URL
The URL interface is used to parse, construct, normalize, and encode URLs. It works by providing properties which allow you to easily read and modify the components of a URL.
URL(request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request.Request<unknown, CfProperties<unknown>>.url: string
The url read-only property of the Request interface contains the URL of the request.
url) const const storeId: string | null
storeId = const url: URL
url.URL.searchParams: URLSearchParams
The searchParams read-only property of the URL interface returns a URLSearchParams object allowing access to the GET decoded query arguments contained in the URL.
searchParams.URLSearchParams.get(name: string): string | null (+1 overload)
The get() method of the URLSearchParams interface returns the first value associated to the given search parameter.
get('storeId')
if (const storeId: string | null
storeId === null) { throw new var Error: ErrorConstructornew (message?: string, options?: ErrorOptions) => Error (+2 overloads)
Error('storeId is required in URL search params') }
return const storeId: string
storeId}3. Worker fetch handler
Section titled “3. Worker fetch handler”The worker routes incoming requests either to the sync backend or to the client Durable Object:
import type { import CfTypes
CfTypes } from '@livestore/sync-cf/cf-worker'import * as import SyncBackend
SyncBackend from '@livestore/sync-cf/cf-worker'
import type { import Env
Env } from './env.ts'import { import storeIdFromRequest
storeIdFromRequest } from './shared.ts'
export default { fetch: <CFHostMetada = unknown>(request: CfTypes.Request<CFHostMetada, CfTypes.CfProperties<CFHostMetada>>, env: Env, ctx: CfTypes.ExecutionContext) => Promise<CfTypes.Response>
fetch: async (request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request: import CfTypes
CfTypes.interface Request<CfHostMetadata = unknown, Cf = CfTypes.CfProperties<CfHostMetadata>>
The Request interface of the Fetch API represents a resource request.
Request, env: Env
env: import Env
Env, ctx: CfTypes.ExecutionContext<unknown>
ctx: import CfTypes
CfTypes.interface ExecutionContext<Props = unknown>
ExecutionContext) => { const const url: URL
url = new var URL: new (url: string | URL, base?: string | URL) => URL
The URL interface is used to parse, construct, normalize, and encode URLs. It works by providing properties which allow you to easily read and modify the components of a URL.
URL(request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request.Request<unknown, CfProperties<unknown>>.url: string
The url read-only property of the Request interface contains the URL of the request.
url)
const const searchParams: { readonly transport: "http" | "ws"; readonly storeId: string; readonly payload?: Json | undefined;} | undefined
searchParams = import SyncBackend
SyncBackend.const matchSyncRequest: (request: CfTypes.Request) => SearchParams | undefined
Extracts the LiveStore sync search parameters from a request. Returns
undefined when the request does not carry valid sync metadata so callers
can fall back to custom routing.
matchSyncRequest(request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request) if (const searchParams: { readonly transport: "http" | "ws"; readonly storeId: string; readonly payload?: Json | undefined;} | undefined
searchParams !== var undefined
undefined) { return import SyncBackend
SyncBackend.const handleSyncRequest: <Env, undefined, unknown, Json>({ request, searchParams: { storeId, payload, transport }, env: explicitlyProvidedEnv, syncBackendBinding, headers, validatePayload, syncPayloadSchema, }: { request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>; searchParams: SearchParams; env?: any; ctx: CfTypes.ExecutionContext; syncBackendBinding: any; headers?: CfTypes.HeadersInit | undefined; validatePayload?: ((payload: Json, context: SyncBackend.ValidatePayloadContext) => void | Promise<void>) | undefined; syncPayloadSchema?: Decoder<Json, never> | undefined;}) => Promise<CfTypes.Response>
Handles LiveStore sync requests (e.g. with search params ?storeId=...&transport=...).
handleSyncRequest({ request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request, searchParams: { readonly transport: "http" | "ws"; readonly storeId: string; readonly payload?: Json | undefined;}
searchParams, env?: any
env, ctx: CfTypes.ExecutionContext<unknown>
Only there for type-level reasons
ctx, syncBackendBinding: any
Binding name of the sync backend Durable Object
syncBackendBinding: 'SYNC_BACKEND_DO', headers?: CfTypes.HeadersInit | undefined
headers: {}, }) }
if (const url: URL
url.URL.pathname: string
The pathname property of the URL interface represents a location in a hierarchical structure. It is a string constructed from a list of path segments, each of which is prefixed by a / character.
pathname.String.endsWith(searchString: string, endPosition?: number): boolean
Returns true if the sequence of elements of searchString converted to a String is the
same as the corresponding elements of this object (converted to a String) starting at
endPosition – length(this). Otherwise returns false.
endsWith('/client-do') === true) { const const storeId: any
storeId = import storeIdFromRequest
storeIdFromRequest(request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request) const const id: any
id = env: Env
env.any
CLIENT_DO.any
idFromName(const storeId: any
storeId) return env: Env
env.any
CLIENT_DO.any
get(const id: any
id).any
fetch(request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request) }
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response
The Response interface of the Fetch API represents the response to a request.
Response('Not found', { ResponseInit.status?: number
status: 404 }) as unknown as import CfTypes
CfTypes.interface Response
The Response interface of the Fetch API represents the response to a request.
Response },} satisfies import SyncBackend
SyncBackend.type CFWorker<TEnv extends SyncBackend.Env = SyncBackend.Env, _T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined> = { fetch: <CFHostMetada = unknown>(request: CfTypes.Request<CFHostMetada>, env: TEnv, ctx: CfTypes.ExecutionContext) => Promise<CfTypes.Response>;}
CFWorker<import Env
Env>import type { (alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback } from '@livestore/adapter-cloudflare'import type { import CfTypes
CfTypes, (alias) interface SyncBackendRpcInterfaceimport SyncBackendRpcInterface
Durable Object interface supporting the DO RPC protocol for DO <> DO syncing.
SyncBackendRpcInterface } from '@livestore/sync-cf/cf-worker'
export type type Env = { CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>; DB: CfTypes.D1Database;}
Env = { type CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>
CLIENT_DO: import CfTypes
CfTypes.class DurableObjectNamespace<T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined>
DurableObjectNamespace<(alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback> type SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>
SYNC_BACKEND_DO: import CfTypes
CfTypes.class DurableObjectNamespace<T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined>
DurableObjectNamespace<(alias) interface SyncBackendRpcInterfaceimport SyncBackendRpcInterface
Durable Object interface supporting the DO RPC protocol for DO <> DO syncing.
SyncBackendRpcInterface> type DB: CfTypes.D1Database
DB: import CfTypes
CfTypes.class D1Database
D1Database}import type { import CfTypes
CfTypes } from '@livestore/sync-cf/cf-worker'
export const const storeIdFromRequest: (request: CfTypes.Request) => string
storeIdFromRequest = (request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request: import CfTypes
CfTypes.interface Request<CfHostMetadata = unknown, Cf = CfTypes.CfProperties<CfHostMetadata>>
The Request interface of the Fetch API represents a resource request.
Request) => { const const url: URL
url = new var URL: new (url: string | URL, base?: string | URL) => URL
The URL interface is used to parse, construct, normalize, and encode URLs. It works by providing properties which allow you to easily read and modify the components of a URL.
URL(request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request.Request<unknown, CfProperties<unknown>>.url: string
The url read-only property of the Request interface contains the URL of the request.
url) const const storeId: string | null
storeId = const url: URL
url.URL.searchParams: URLSearchParams
The searchParams read-only property of the URL interface returns a URLSearchParams object allowing access to the GET decoded query arguments contained in the URL.
searchParams.URLSearchParams.get(name: string): string | null (+1 overload)
The get() method of the URLSearchParams interface returns the first value associated to the given search parameter.
get('storeId')
if (const storeId: string | null
storeId === null) { throw new var Error: ErrorConstructornew (message?: string, options?: ErrorOptions) => Error (+2 overloads)
Error('storeId is required in URL search params') }
return const storeId: string
storeId}API reference
Section titled “API reference”createStoreDoPromise(options)
Section titled “createStoreDoPromise(options)”Creates a LiveStore instance inside a Durable Object.
Options:
schema– LiveStore schema definitionstoreId– Unique identifier for the storeclientId– Client identifiersessionId– Session identifier (usenanoid())durableObject– Context about the Durable Object hosting the store:state– Durable Object state handle (for examplethis.ctx)env– Environment bindings for the Durable ObjectbindingName– Name other workers use to reach this Durable Object
syncBackendStub– Durable Object stub used to reach the sync backendlivePull– Enable real-time updates (default:false)resetPersistence– Drop LiveStore state/eventlog persistence before booting (development only, default:false)logger?– Optional Effect logger layer to customize formatting/outputlogLevel?– Optional minimum log level (use"None"to disable logs)
syncUpdateRpc(payload, storeId)
Section titled “syncUpdateRpc(payload, storeId)”Client Durable Objects must implement this method so the sync backend can deliver live updates to them. Forward the DO’s ctx and the payload to handleSyncUpdateRpc(ctx, payload) (see the client Durable Object example above).
Cloudflare can evict a Durable Object at any time and start a fresh instance on the next request. Because this call is what wakes the DO, it can arrive at an instance that no longer has your store in memory — and a fresh instance can’t tell which storeId it belongs to on its own. That’s why the sync backend also passes the storeId. You choose how to use it:
- Eager (stay in sync): load the store before delivering — set
this.storeId = storeId, thenawait this.getStore()(idempotent, and it catches up on any updates the DO missed while it was gone). The DO stays in sync whenever it is awake and costs nothing while idle. - Reactive (recover lazily): ignore
storeId(you can omit the parameter). The DO drops that one live update and picks up the changes the next time your code loads the store (e.g. the nextfetch). Simpler, but live updates are not applied while the DO is idle.
Pass storeId to your store load (getStore), not to handleSyncUpdateRpc — that function only needs ctx and payload.
Resetting LiveStore persistence (development only)
Section titled “Resetting LiveStore persistence (development only)”When iterating locally, you can instruct the adapter to wipe the Durable Object’s LiveStore databases before booting by enabling resetPersistence. Guard this behind a protected route or admin token.
import { const createStoreDoPromise: <TSchema extends LiveStoreSchema, TEnv, TState extends CfTypes.DurableObjectState = CfTypes.DurableObjectState<unknown>>(options: CreateStoreDoOptions<TSchema, TEnv, TState>) => Promise<Store<TSchema, {}>>
Promise-based wrapper around createStoreDo for simpler async/await usage.
Equivalent to calling createStoreDo(options).pipe(Effect.runPromise) with
logging configured automatically.
createStoreDoPromise } from '@livestore/adapter-cloudflare'import { function nanoid(size?: number): string
Generate secure URL-friendly unique ID.
By default, the ID will have 21 symbols to have a collision probability
similar to UUID v4.
import { nanoid } from 'nanoid'model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
nanoid } from '@livestore/livestore'import type { import CfTypes
CfTypes } from '@livestore/sync-cf/cf-worker'
import type { import Env
Env } from './env.ts'import { import schema
schema } from './schema.ts'
export const const maybeResetStore: ({ request, env, ctx, }: { request: Request; env: Env; ctx: CfTypes.DurableObjectState;}) => Promise<Store<any, {}>>
maybeResetStore = async ({ request: Request<unknown, CfProperties<unknown>>
request, env: Env
env, ctx: CfTypes.DurableObjectState<unknown>
ctx,}: { request: Request<unknown, CfProperties<unknown>>
request: interface Request<CfHostMetadata = unknown, Cf = CfProperties<CfHostMetadata>>
The Request interface of the Fetch API represents a resource request.
Request env: Env
env: import Env
Env ctx: CfTypes.DurableObjectState<unknown>
ctx: import CfTypes
CfTypes.interface DurableObjectState<Props = unknown>
DurableObjectState}) => { const const url: URL
url = new var URL: new (url: string | URL, base?: string | URL) => URL
The URL interface is used to parse, construct, normalize, and encode URLs. It works by providing properties which allow you to easily read and modify the components of a URL.
URL(request: Request<unknown, CfProperties<unknown>>
request.Request<unknown, CfProperties<unknown>>.url: string
The url read-only property of the Request interface contains the URL of the request.
url) const const shouldReset: boolean
shouldReset = const url: URL
url.URL.pathname: string
The pathname property of the URL interface represents a location in a hierarchical structure. It is a string constructed from a list of path segments, each of which is prefixed by a / character.
pathname === '/internal/livestore-dev-reset'
const const storeId: string
storeId = const url: URL
url.URL.searchParams: URLSearchParams
The searchParams read-only property of the URL interface returns a URLSearchParams object allowing access to the GET decoded query arguments contained in the URL.
searchParams.URLSearchParams.get(name: string): string | null (+1 overload)
The get() method of the URLSearchParams interface returns the first value associated to the given search parameter.
get('storeId') ?? function nanoid(size?: number): string
Generate secure URL-friendly unique ID.
By default, the ID will have 21 symbols to have a collision probability
similar to UUID v4.
import { nanoid } from 'nanoid'model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
nanoid()
const const store: Store<any, {}>
store = await createStoreDoPromise<any, Env, CfTypes.DurableObjectState<unknown>>(options: CreateStoreDoOptions<any, Env, CfTypes.DurableObjectState<unknown>>): Promise<Store<any, {}>>
Promise-based wrapper around createStoreDo for simpler async/await usage.
Equivalent to calling createStoreDo(options).pipe(Effect.runPromise) with
logging configured automatically.
createStoreDoPromise({ schema: any
LiveStore schema that defines state, migrations, and validators.
schema, storeId: string
Logical identifier for the store instance persisted inside the Durable Object.
storeId, clientId: string
Unique identifier for the client that owns the Durable Object instance.
clientId: 'client-do', sessionId: string
Identifier for the LiveStore session running inside the Durable Object.
sessionId: function nanoid(size?: number): string
Generate secure URL-friendly unique ID.
By default, the ID will have 21 symbols to have a collision probability
similar to UUID v4.
import { nanoid } from 'nanoid'model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
nanoid(), durableObject: { ctx: CfTypes.DurableObjectState<unknown>; env: Env; bindingName: any;}
Runtime details about the Durable Object this store runs inside. Needed for sync backend to call back to this instance.
durableObject: { ctx: CfTypes.DurableObjectState<unknown>
Durable Object state handle (e.g. this.ctx).
ctx, env: Env
Environment bindings associated with the Durable Object.
env, bindingName: any
Binding name Cloudflare uses to reach this Durable Object from other workers.
bindingName: 'CLIENT_DO' }, syncBackendStub: CfTypes.DurableObjectStub<SyncBackendRpcInterface>
RPC stub pointing at the sync backend Durable Object used for replication.
syncBackendStub: env: Env
env.any
SYNC_BACKEND_DO.any
get(env: Env
env.any
SYNC_BACKEND_DO.any
idFromName(const storeId: string
storeId)), livePull?: boolean
Enables live pull mode to receive sync updates via Durable Object RPC callbacks.
livePull: true, resetPersistence?: boolean
Clears existing Durable Object persistence before bootstrapping the store.
Note: Only use this for development purposes.
resetPersistence: const shouldReset: boolean
shouldReset, })
return const store: Store<any, {}>
store}import type { (alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback } from '@livestore/adapter-cloudflare'import type { import CfTypes
CfTypes, (alias) interface SyncBackendRpcInterfaceimport SyncBackendRpcInterface
Durable Object interface supporting the DO RPC protocol for DO <> DO syncing.
SyncBackendRpcInterface } from '@livestore/sync-cf/cf-worker'
export type type Env = { CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>; DB: CfTypes.D1Database;}
Env = { type CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>
CLIENT_DO: import CfTypes
CfTypes.class DurableObjectNamespace<T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined>
DurableObjectNamespace<(alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback> type SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>
SYNC_BACKEND_DO: import CfTypes
CfTypes.class DurableObjectNamespace<T extends CfTypes.Rpc.DurableObjectBranded | undefined = undefined>
DurableObjectNamespace<(alias) interface SyncBackendRpcInterfaceimport SyncBackendRpcInterface
Durable Object interface supporting the DO RPC protocol for DO <> DO syncing.
SyncBackendRpcInterface> type DB: CfTypes.D1Database
DB: import CfTypes
CfTypes.class D1Database
D1Database}import { import Events
Events, const makeSchema: <TInputSchema extends InputSchema>(inputSchema: TInputSchema) => FromInputSchema.DeriveSchema<TInputSchema>
makeSchema, import Schema
Schema, 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<...>>;}
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 number of milliseconds since the Unix epoch is decoded as a Date.
Encoding:
A Date is encoded as its millisecond timestamp.
Gotchas
This schema accepts any number, including NaN, Infinity, and -Infinity.
Those values decode to invalid Date instances.
DateFromMillis }), }, }),}
export const const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">>
todoCreated: import Events
Events.synced<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">>(args: { name: "v1.TodoCreated"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">, never, never>;} & Omit<...>): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String;}, "Encoded">, never, never>
schema: import Schema
Schema.function Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>(fields: { readonly id: Schema.String; readonly text: Schema.String;}): Schema.Struct<{ readonly id: Schema.String; readonly text: Schema.String;}>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, text: Schema.String
text: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">>
todoCompleted: import Events
Events.synced<"v1.TodoCompleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">>(args: { name: "v1.TodoCompleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, false>, "derived" | "clientOnly">): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoCompleted"
name: 'v1.TodoCompleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">, 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.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">>
todoUncompleted: import Events
Events.synced<"v1.TodoUncompleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">>(args: { name: "v1.TodoUncompleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">, never, never>;} & Omit<State.SQLite.DefineEventOptions<Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, false>, "derived" | "clientOnly">): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoUncompleted"
name: 'v1.TodoUncompleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String;}, "Encoded">, 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.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String }), }), todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>
todoDeleted: import Events
Events.synced<"v1.TodoDeleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">>(args: { name: "v1.TodoDeleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString; }, "Encoded">, never, never>;} & Omit<...>): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoDeleted"
name: 'v1.TodoDeleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly deletedAt: Schema.DateFromString;}, "Encoded">, 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.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ id: Schema.String
id: import Schema
Schema.const String: Schema.String
Type-level representation of
String
.
Schema for string values. Validates that the input is typeof "string".
String, deletedAt: Schema.DateFromString
deletedAt: import Schema
Schema.const DateFromString: Schema.DateFromString
Type-level representation of
DateFromString
.
Schema that decodes a string into a JavaScript Date.
When to use
Use to model string-encoded dates that decode to JavaScript Date objects
and encode back to strings.
Details
Decoding:
The string is passed to JavaScript Date construction.
Encoding:
A valid Date is encoded as an ISO string; an invalid Date is encoded as
"Invalid Date".
Gotchas
Invalid date strings can decode to invalid Date instances.
DateFromString.Bottom<unknown, unknown, unknown, unknown, Declaration, decodeTo<Date, String, never, never>, unknown, unknown, readonly [], unknown, "readonly", "required", "no-default", "readonly", "required">.check(checks_0: Check<Date>, ...checks: Check<Date>[]): Schema.DateFromString
check(import Schema
Schema.function isDateValid(annotations?: Schema.Annotations.Filter): Filter<globalThis.Date>
Validates that a Date object represents a valid date (not an invalid date
like new Date("invalid")).
Details
JSON Schema:
This check does not have a direct JSON Schema equivalent, as JSON Schema
validates date strings, not Date objects.
Arbitrary:
When generating test data with fast-check, this applies a valid: true
constraint to ensure generated Date objects are valid.
isDateValid()), }), }), todoClearedCompleted: State.SQLite.EventDef<"v1.TodoClearedCompleted", Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Encoded">>
todoClearedCompleted: import Events
Events.synced<"v1.TodoClearedCompleted", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Encoded">>(args: { name: "v1.TodoClearedCompleted"; schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString; }, "Type">, Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString; }, "Encoded">, never, never>;} & Omit<...>): State.SQLite.EventDef<...>export synced
Creates a synced event definition.
Synced events are sent to the sync backend and distributed to all connected
clients. Use this for collaborative data that should be shared across users
and devices.
Event names should be versioned (e.g., v1.TodoCreated) to support
schema evolution over time.
synced({ name: "v1.TodoClearedCompleted"
name: 'v1.TodoClearedCompleted', schema: Schema.Codec<Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Type">, Schema.Struct.ReadonlySide<{ readonly deletedAt: Schema.DateFromString;}, "Encoded">, 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.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number, email: Schema.optionalKey(Schema.String)})
// { readonly name: string; readonly age: number; readonly email?: string }type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })console.log(alice)// { name: 'Alice', age: 30 }
Struct({ deletedAt: Schema.DateFromString
deletedAt: import Schema
Schema.const DateFromString: Schema.DateFromString
Type-level representation of
DateFromString
.
Schema that decodes a string into a JavaScript Date.
When to use
Use to model string-encoded dates that decode to JavaScript Date objects
and encode back to strings.
Details
Decoding:
The string is passed to JavaScript Date construction.
Encoding:
A valid Date is encoded as an ISO string; an invalid Date is encoded as
"Invalid Date".
Gotchas
Invalid date strings can decode to invalid Date instances.
DateFromString.Bottom<unknown, unknown, unknown, unknown, Declaration, decodeTo<Date, String, never, never>, unknown, unknown, readonly [], unknown, "readonly", "required", "no-default", "readonly", "required">.check(checks_0: Check<Date>, ...checks: Check<Date>[]): Schema.DateFromString
check(import Schema
Schema.function isDateValid(annotations?: Schema.Annotations.Filter): Filter<globalThis.Date>
Validates that a Date object represents a valid date (not an invalid date
like new Date("invalid")).
Details
JSON Schema:
This check does not have a direct JSON Schema equivalent, as JSON Schema
validates date strings, not Date objects.
Arbitrary:
When generating test data with fast-check, this applies a valid: true
constraint to ensure generated Date objects are valid.
isDateValid()) }), }),}
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>>; "v1.TodoUncompleted": State.SQLite.Materializer<...>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers = import State
State.import SQLite
SQLite.const materializers: <{ todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>;}>(_eventDefRecord: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>;}, handlers: { ...;}) => { ...;}
Builder function for creating a type-safe materializer map.
This is the primary way to define materializers in LiveStore. It ensures:
- Every non-derived event has a corresponding materializer
- Materializer argument types match their event schemas
- Derived events are excluded from the required handlers
materializers(const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>;}
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<...>>;}
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 Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { ...;}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table.
insert({ id: string
id, text?: string
text, completed?: boolean
completed: 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<...>>;}
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<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly 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<...>>;}
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<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: 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<...>>;}
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<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly 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<...>>;}
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<Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">>) => QueryBuilder<readonly Schema.Struct.ReadonlySide<{ readonly id: Schema.Codec<string, string, never, never>; readonly text: Schema.Codec<string, string, never, never>; readonly completed: Schema.Codec<boolean, number, never, never>; readonly deletedAt: Schema.Codec<Date | null, number | null, never, never>;}, "Type">[], State.SQLite.TableDefBase<...>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly 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<...>>; }; 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<...>>; }; 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<...>>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>>; "v1.TodoUncompleted": State.SQLite.Materializer<...>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}>(inputSchema: { events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct<Fields extends Schema.Struct.Fields>.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; readonly text: Schema.String; }, "Encoded">>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Type">, Schema.Struct.ReadonlySide<{ readonly id: Schema.String; }, "Encoded">>; todoUncompleted: State.SQLite.EventDef<...>; todoDeleted: State.SQLite.EventDef<...>; todoClearedCompleted: State.SQLite.EventDef<...>;}
events, state: InternalState
state })Advanced features
Section titled “Advanced features”- Use
livePull: trueto receive push-based updates via Durable Object RPC callbacks. - Subscribe to data changes inside the Durable Object to trigger side effects (see the client Durable Object example).
- Wire additional routes in the worker fetch handler to expose debugging endpoints or admin operations.
For sync backend-related APIs like makeDurableObject, handleSyncRequest, and matchSyncRequest, see the Cloudflare sync provider documentation.