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; ADMIN_SECRET: string;}
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 type ADMIN_SECRET: string
ADMIN_SECRET: string}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, {}>>
createStoreDoPromise } from '@livestore/adapter-cloudflare'import { function nanoid<Type extends string>(size?: number): Type
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 = {}>
Store, type type Unsubscribe = () => void
Unsubscribe } from '@livestore/livestore'import { const handleSyncUpdateRpc: (payload: unknown) => Promise<void>
import { DurableObject } from 'cloudflare:workers'import { ClientDoWithRpcCallback } from '@livestore/common-cf'
export class MyDurableObject extends DurableObject implements ClientDoWithRpcCallback { // ...
async syncUpdateRpc(payload: RpcMessage.ResponseChunkEncoded) { return handleSyncUpdateRpc(payload) }}
handleSyncUpdateRpc } from '@livestore/sync-cf/client'import type { type Env = { CLIENT_DO: DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: DurableObjectNamespace<SyncBackendRpcInterface>; DB: D1Database; ADMIN_SECRET: string;}
Env } from './env.ts'import { const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>
schema, const tables: { todos: TableDef<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { columnType: "integer"; ... 4 more ...; autoIncrement: false; }; }>, WithDefaults<...>, Schema<...>>;}
tables } from './schema.ts'import { const storeIdFromRequest: (request: Request) => string
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<type Env = { CLIENT_DO: DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: DurableObjectNamespace<SyncBackendRpcInterface>; DB: D1Database; ADMIN_SECRET: string;}
Env> implements (alias) interface ClientDoWithRpcCallbackimport ClientDoWithRpcCallback
ClientDoWithRpcCallback { 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<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}> | undefined
cachedStore: class Store<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}>
Store<typeof const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>
schema> | undefined private LiveStoreClientDO.storeSubscription: Unsubscribe | undefined
storeSubscription: type Unsubscribe = () => void
Unsubscribe | undefined private readonly LiveStoreClientDO.todosQuery: QueryBuilder<readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[], TableDefBase<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, WithDefaults<...>>, "select" | ... 3 more ... | "row">
todosQuery = const tables: { todos: TableDef<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, WithDefaults<...>, Schema<...>>;}
tables.todos: TableDef<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, WithDefaults<...>, Schema<...>>
todos.select: <"id" | "text" | "deletedAt" | "completed">(...columns: ("id" | "text" | "deletedAt" | "completed")[]) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[], TableDefBase<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, WithDefaults<...>>, "select" | ... 3 more ... | "row"> (+1 overload)
Select multiple columns
select()
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.
This Fetch API interface 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.
This Fetch API interface 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 = function storeIdFromRequest(request: Request): string
storeIdFromRequest(request: Request<unknown, CfProperties<unknown>>
request)
const const store: Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>
store = await this.LiveStoreClientDO.getStore(): Promise<Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>>
getStore() await this.LiveStoreClientDO.subscribeToStore(): Promise<void>
subscribeToStore()
const const todos: readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[]
todos = const store: Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>
store.Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<...>; todoUncompleted: EventDef<...>; todoDeleted: EventDef<...>; todoClearedCompleted: EventDef<...>; }; state: InternalState; }>, {}>.query: <readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[]>(query: Queryable<readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[]> | { query: string; bindValues: Bindable; schema?: Schema<readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean; }[], readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean; }[], never>;}, options?: { otelContext?: Context; debugRefreshReason?: RefreshReason;}) => readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[]
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: QueryBuilder<readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[], TableDefBase<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, WithDefaults<...>>, "select" | ... 3 more ... | "row">
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.
This Fetch API interface 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: readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[]
todos, null, 2), { ResponseInit.headers?: HeadersInit
headers: { 'Content-Type': 'application/json' }, }) }
private async LiveStoreClientDO.getStore(): Promise<Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>>
getStore() { if (this.LiveStoreClientDO.cachedStore: Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}> | undefined
cachedStore !== var undefined
undefined) { return this.LiveStoreClientDO.cachedStore: Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>
cachedStore }
const const storeId: string
storeId = this.LiveStoreClientDO.storeId: string | undefined
storeId ?? nanoid<string>(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<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>
store = await createStoreDoPromise<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, Env, DurableObjectState<...>>(options: CreateStoreDoOptions<...>): Promise<...>
createStoreDoPromise({ schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>
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: nanoid<string>(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: "CLIENT_DO" | "SYNC_BACKEND_DO";}
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: "CLIENT_DO" | "SYNC_BACKEND_DO"
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.type SYNC_BACKEND_DO: DurableObjectNamespace<SyncBackendRpcInterface>
SYNC_BACKEND_DO.DurableObjectNamespace<SyncBackendRpcInterface>.get(id: DurableObjectId, options?: DurableObjectNamespaceGetDurableObjectOptions): DurableObjectStub<SyncBackendRpcInterface>
get(this.CloudflareWorkersModule.DurableObject<Env, {}>.env: Env
env.type SYNC_BACKEND_DO: DurableObjectNamespace<SyncBackendRpcInterface>
SYNC_BACKEND_DO.DurableObjectNamespace<SyncBackendRpcInterface>.idFromName(name: string): DurableObjectId
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<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}> | undefined
cachedStore = const store: Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>
store return const store: Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>
store }
private async LiveStoreClientDO.subscribeToStore(): Promise<void>
subscribeToStore() { const const store: Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>
store = await this.LiveStoreClientDO.getStore(): Promise<Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>>
getStore()
if (this.LiveStoreClientDO.storeSubscription: Unsubscribe | undefined
storeSubscription === var undefined
undefined) { this.LiveStoreClientDO.storeSubscription: Unsubscribe | undefined
storeSubscription = const store: Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>
store.Store<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}>.subscribe: <readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[]>(query: Queryable<readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[]>, onUpdate: (value: readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[]) => void, options?: SubscribeOptions<readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[]> | undefined) => Unsubscribe (+1 overload)
subscribe(this.LiveStoreClientDO.todosQuery: QueryBuilder<readonly { readonly id: string; readonly text: string; readonly deletedAt: Date | null; readonly completed: boolean;}[], TableDefBase<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, WithDefaults<...>>, "select" | ... 3 more ... | "row">
todosQuery, (todos: readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[]
todos: interface ReadonlyArray<T>
ReadonlyArray<typeof const tables: { todos: TableDef<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, WithDefaults<...>, Schema<...>>;}
tables.todos: TableDef<SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, WithDefaults<...>, Schema<...>>
todos.type Type: { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}
Type>) => { var console: Console
The console module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
- A
Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
- A global
console instance configured to write to process.stdout and
process.stderr. The global console can be used without importing the node:console module.
Warning: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the note on process I/O for
more information.
Example using the global console:
console.log('hello world');// Prints: hello world, to stdoutconsole.log('hello %s', 'world');// Prints: hello world, to stdoutconsole.error(new Error('Whoops, something bad happened'));// Prints error message and stack trace to stderr:// Error: Whoops, something bad happened// at [eval]:5:15// at Script.runInThisContext (node:vm:132:18)// at Object.runInThisContext (node:vm:309:38)// at node:internal/process/execution:77:19// at [eval]-wrapper:6:22// at evalScript (node:internal/process/execution:76:60)// at node:internal/main/eval_string:23:3
const name = 'Will Robinson';console.warn(`Danger ${name}! Danger!`);// Prints: Danger Will Robinson! Danger!, to stderr
Example using the Console class:
const out = getStreamSomehow();const err = getStreamSomehow();const myConsole = new console.Console(out, err);
myConsole.log('hello world');// Prints: hello world, to outmyConsole.log('hello %s', 'world');// Prints: hello world, to outmyConsole.error(new Error('Whoops, something bad happened'));// Prints: [Error: Whoops, something bad happened], to err
const name = 'Will Robinson';myConsole.warn(`Danger ${name}! Danger!`);// Prints: Danger Will Robinson! Danger!, to err
console.Console.log(message?: any, ...optionalParams: any[]): void (+3 overloads)
Prints to stdout with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to printf(3)
(the arguments are all passed to util.format()).
const count = 5;console.log('count: %d', count);// Prints: count: 5, to stdoutconsole.log('count:', count);// Prints: count: 5, to stdout
See util.format() for more information.
log(`todos for store (${this.LiveStoreClientDO.storeId: string | undefined
storeId})`, todos: readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[]
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) }
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: unknown): Promise<void>
syncUpdateRpc(payload: unknown
payload: unknown) { await function handleSyncUpdateRpc(payload: unknown): Promise<void>
import { DurableObject } from 'cloudflare:workers'import { ClientDoWithRpcCallback } from '@livestore/common-cf'
export class MyDurableObject extends DurableObject implements ClientDoWithRpcCallback { // ...
async syncUpdateRpc(payload: RpcMessage.ResponseChunkEncoded) { return handleSyncUpdateRpc(payload) }}
handleSyncUpdateRpc(payload: unknown
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; ADMIN_SECRET: string;}
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 type ADMIN_SECRET: string
ADMIN_SECRET: string}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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { columnType: "integer"; ... 4 more ...; autoIncrement: false; };}, Partial<...>>(args: { ...;} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotations({ 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,}).annotations({ 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}
columns: { id: { columnType: "text"; schema: Schema.Schema<string, string, 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.Schema<string, string, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Schema<string, string, 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.Schema<string, string, never>; default?: ""; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text({ default?: ""
default: '' }), completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, 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.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
boolean({ default?: false
default: false }), deletedAt: { columnType: "integer"; schema: Schema.Schema<Date | null, number | null, 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.Schema<Date, number, never>; default?: typeof NoDefault; nullable?: true; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Schema<Date | null, number | null, never>; default: None<never>; nullable: true; primaryKey: false; autoIncrement: false;} (+1 overload)
integer({ nullable?: true
nullable: true, schema?: Schema.Schema<Date, number, never>
schema: import Schema
Schema.class DateFromNumber
Defines a schema that converts a number into a Date object using the new Date constructor. This schema does not validate the numerical input,
allowing potentially invalid values such as NaN, Infinity, and
-Infinity to be converted into Date objects. During the encoding process,
any invalid Date object will be encoded to NaN.
DateFromNumber }), }, }),}
export const const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Schema<{ readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly text: string; readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>export synced
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Schema<{ readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String; text: typeof Schema.String;}>(fields: { id: typeof Schema.String; text: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.String; text: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String, text: typeof Schema.String
text: import Schema
Schema.class Stringexport String
String }), }), todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}, false>
todoCompleted: import Events
Events.synced<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoCompleted"; schema: Schema.Schema<{ readonly id: string; }, { readonly id: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}, false>export synced
synced({ name: "v1.TodoCompleted"
name: 'v1.TodoCompleted', schema: Schema.Schema<{ readonly id: string;}, { readonly id: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String;}>(fields: { id: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String }), }), todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}, false>
todoUncompleted: import Events
Events.synced<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoUncompleted"; schema: Schema.Schema<{ readonly id: string; }, { readonly id: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}, false>export synced
synced({ name: "v1.TodoUncompleted"
name: 'v1.TodoUncompleted', schema: Schema.Schema<{ readonly id: string;}, { readonly id: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String;}>(fields: { id: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String }), }), todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, false>
todoDeleted: import Events
Events.synced<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>(args: { name: "v1.TodoDeleted"; schema: Schema.Schema<{ readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, false>export synced
synced({ name: "v1.TodoDeleted"
name: 'v1.TodoDeleted', schema: Schema.Schema<{ readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String; deletedAt: typeof Schema.Date;}>(fields: { id: typeof Schema.String; deletedAt: typeof Schema.Date;}): Schema.Struct<{ id: typeof Schema.String; deletedAt: typeof Schema.Date;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String, deletedAt: typeof Schema.Date
deletedAt: import Schema
Schema.class Dateexport Date
This schema converts a string into a Date object using the new Date
constructor. It ensures that only valid date strings are accepted,
rejecting any strings that would result in an invalid date, such as new Date("Invalid Date").
Date }), }), todoClearedCompleted: State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}, false>
todoClearedCompleted: import Events
Events.synced<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>(args: { name: "v1.TodoClearedCompleted"; schema: Schema.Schema<{ readonly deletedAt: Date; }, { readonly deletedAt: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}, false>export synced
synced({ name: "v1.TodoClearedCompleted"
name: 'v1.TodoClearedCompleted', schema: Schema.Schema<{ readonly deletedAt: Date;}, { readonly deletedAt: string;}, never>
schema: import Schema
Schema.function Struct<{ deletedAt: typeof Schema.Date;}>(fields: { deletedAt: typeof Schema.Date;}): Schema.Struct<{ deletedAt: typeof Schema.Date;}> (+1 overload)
Struct({ deletedAt: typeof Schema.Date
deletedAt: import Schema
Schema.class Dateexport Date
This schema converts a string into a Date object using the new Date
constructor. It ensures that only valid date strings are accepted,
rejecting any strings that would result in an invalid date, such as new Date("Invalid Date").
Date }), }),}
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>>; "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", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>;}>(_eventDefRecord: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>;}, handlers: { ...;}) => { ...;}
materializers(const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.insert: (values: { readonly id: string; readonly text?: string; readonly completed?: boolean; readonly deletedAt?: Date | null;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table
Example:
db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' })
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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.update: (values: Partial<{ readonly text: string; readonly id: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly id: string | { op: QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: QueryBuilder.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+2 overloads)
where({ id?: string | { op: QueryBuilder.WhereOps.SingleValue; 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.update: (values: Partial<{ readonly text: string; readonly id: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: false }).where: (params: Partial<{ readonly id: string | { op: QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: QueryBuilder.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+2 overloads)
where({ id?: string | { op: QueryBuilder.WhereOps.SingleValue; 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.update: (values: Partial<{ readonly text: string; readonly id: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: string | { op: QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: QueryBuilder.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+2 overloads)
where({ id?: string | { op: QueryBuilder.WhereOps.SingleValue; 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.update: (values: Partial<{ readonly text: string; readonly id: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: string | { op: QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: QueryBuilder.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+2 overloads)
where({ completed?: boolean | { op: QueryBuilder.WhereOps.SingleValue; 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; }; materializers: { ...; };}>(inputSchema: { tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}>(inputSchema: { events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; 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>>
This Fetch API interface 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 URL.
URL(request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request.Request<unknown, CfProperties<unknown>>.url: string
Returns the URL of request as a string.
url) const const storeId: string | null
storeId = const url: URL
url.URL.searchParams: URLSearchParams
The searchParams read-only property of the access to the [MISSING: httpmethod('GET')] decoded query arguments contained in the URL.
searchParams.URLSearchParams.get(name: string): string | null
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 { type Env = { CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackend.SyncBackendRpcInterface>; DB: CfTypes.D1Database; ADMIN_SECRET: string;}
Env } from './env.ts'import { const storeIdFromRequest: (request: CfTypes.Request) => string
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>>
This Fetch API interface represents a resource request.
Request, env: Env
env: type Env = { CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackend.SyncBackendRpcInterface>; DB: CfTypes.D1Database; ADMIN_SECRET: string;}
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 URL.
URL(request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request.Request<unknown, CfProperties<unknown>>.url: string
Returns the URL of request as a string.
url)
const const searchParams: { readonly storeId: string; readonly payload: JsonValue | undefined; readonly transport: "http" | "ws";} | 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 storeId: string; readonly payload: JsonValue | undefined; readonly transport: "http" | "ws";} | undefined
searchParams !== var undefined
undefined) { return import SyncBackend
SyncBackend.const handleSyncRequest: <Env, undefined, unknown, JsonValue>({ request, searchParams: { storeId, payload, transport }, env: explicitlyProvidedEnv, syncBackendBinding, headers, validatePayload, syncPayloadSchema, }: { request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>; searchParams: SearchParams; env?: Env | undefined; ctx: CfTypes.ExecutionContext; syncBackendBinding: "SYNC_BACKEND_DO" | "CLIENT_DO"; headers?: CfTypes.HeadersInit | undefined; validatePayload?: ((payload: JsonValue, context: { storeId: string; }) => void | Promise<void>) | undefined; syncPayloadSchema?: Schema<JsonValue, JsonValue, 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 storeId: string; readonly payload: JsonValue | undefined; readonly transport: "http" | "ws";}
searchParams, env?: Env | undefined
env, ctx: CfTypes.ExecutionContext<unknown>
Only there for type-level reasons
ctx, syncBackendBinding: "SYNC_BACKEND_DO" | "CLIENT_DO"
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.
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')) { const const storeId: string
storeId = function storeIdFromRequest(request: CfTypes.Request): string
storeIdFromRequest(request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request) const const id: CfTypes.DurableObjectId
id = env: Env
env.type CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>
CLIENT_DO.DurableObjectNamespace<ClientDoWithRpcCallback>.idFromName(name: string): CfTypes.DurableObjectId
idFromName(const storeId: string
storeId) return env: Env
env.type CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>
CLIENT_DO.DurableObjectNamespace<ClientDoWithRpcCallback>.get(id: CfTypes.DurableObjectId, options?: CfTypes.DurableObjectNamespaceGetDurableObjectOptions): CfTypes.DurableObjectStub<ClientDoWithRpcCallback>
get(const id: CfTypes.DurableObjectId
id).function fetch(input: CfTypes.RequestInfo | CfTypes.URL, init?: CfTypes.RequestInit): Promise<CfTypes.Response>
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.
This Fetch API interface represents the response to a request.
Response('Not found', { ResponseInit.status?: number
status: 404 }) as unknown as import CfTypes
CfTypes.interface Response
This Fetch API interface 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<type Env = { CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackend.SyncBackendRpcInterface>; DB: CfTypes.D1Database; ADMIN_SECRET: string;}
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; ADMIN_SECRET: string;}
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 type ADMIN_SECRET: string
ADMIN_SECRET: string}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>>
This Fetch API interface 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 URL.
URL(request: CfTypes.Request<unknown, CfTypes.CfProperties<unknown>>
request.Request<unknown, CfProperties<unknown>>.url: string
Returns the URL of request as a string.
url) const const storeId: string | null
storeId = const url: URL
url.URL.searchParams: URLSearchParams
The searchParams read-only property of the access to the [MISSING: httpmethod('GET')] decoded query arguments contained in the URL.
searchParams.URLSearchParams.get(name: string): string | null
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)
syncUpdateRpc(payload)
Section titled “syncUpdateRpc(payload)”Client Durable Objects must implement this method so the sync backend can deliver live updates. createStoreDoPromise wires it up automatically—just forward the payload to handleSyncUpdateRpc (see the client Durable Object example above).
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, {}>>
createStoreDoPromise } from '@livestore/adapter-cloudflare'import { function nanoid<Type extends string>(size?: number): Type
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 { type Env = { CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>; DB: CfTypes.D1Database; ADMIN_SECRET: string;}
Env } from './env.ts'import { const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>
schema } from './schema.ts'
export const const maybeResetStore: ({ request, env, ctx, }: { request: Request; env: Env; ctx: CfTypes.DurableObjectState;}) => Promise<Store<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { ...; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>>
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.
This Fetch API interface represents a resource request.
Request env: Env
env: type Env = { CLIENT_DO: CfTypes.DurableObjectNamespace<ClientDoWithRpcCallback>; SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>; DB: CfTypes.D1Database; ADMIN_SECRET: string;}
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 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.
Returns the URL of request as a string.
url) const const shouldReset: boolean
shouldReset = env: Env
env.type ADMIN_SECRET: string
ADMIN_SECRET === const url: URL
url.URL.searchParams: URLSearchParams
The searchParams read-only property of the access to the [MISSING: httpmethod('GET')] decoded query arguments contained in the URL.
searchParams.URLSearchParams.get(name: string): string | null
The get() method of the URLSearchParams interface returns the first value associated to the given search parameter.
get('token') && const url: URL
url.URL.pathname: string
The pathname property of the URL interface represents a location in a hierarchical structure.
pathname === '/internal/livestore-dev-reset'
const const storeId: string
storeId = const url: URL
url.URL.searchParams: URLSearchParams
The searchParams read-only property of the access to the [MISSING: httpmethod('GET')] decoded query arguments contained in the URL.
searchParams.URLSearchParams.get(name: string): string | null
The get() method of the URLSearchParams interface returns the first value associated to the given search parameter.
get('storeId') ?? nanoid<string>(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<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>
store = await createStoreDoPromise<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, Env, CfTypes.DurableObjectState<...>>(options: CreateStoreDoOptions<...>): Promise<...>
createStoreDoPromise({ schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>
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: nanoid<string>(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: "CLIENT_DO" | "SYNC_BACKEND_DO";}
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: "CLIENT_DO" | "SYNC_BACKEND_DO"
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.type SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>
SYNC_BACKEND_DO.DurableObjectNamespace<SyncBackendRpcInterface>.get(id: CfTypes.DurableObjectId, options?: CfTypes.DurableObjectNamespaceGetDurableObjectOptions): CfTypes.DurableObjectStub<SyncBackendRpcInterface>
get(env: Env
env.type SYNC_BACKEND_DO: CfTypes.DurableObjectNamespace<SyncBackendRpcInterface>
SYNC_BACKEND_DO.DurableObjectNamespace<SyncBackendRpcInterface>.idFromName(name: string): CfTypes.DurableObjectId
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<FromInputSchema.DeriveSchema<{ events: { todoCreated: EventDef<"v1.TodoCreated", { readonly id: string; readonly text: string; }, { readonly id: string; readonly text: string; }, false>; todoCompleted: EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: EventDef<...>; }; state: InternalState;}>, {}>
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; ADMIN_SECRET: string;}
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 type ADMIN_SECRET: string
ADMIN_SECRET: string}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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables = { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos: import State
State.import SQLite
SQLite.function table<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { columnType: "integer"; ... 4 more ...; autoIncrement: false; };}, Partial<...>>(args: { ...;} & Partial<...>): State.SQLite.TableDef<...> (+2 overloads)
Creates a SQLite table definition from columns or an Effect Schema.
This function supports two main ways to define a table:
- Using explicit column definitions
- Using an Effect Schema (either the
name property needs to be provided or the schema needs to have a title/identifier)
// Using explicit columnsconst usersTable = State.SQLite.table({ name: 'users', columns: { id: State.SQLite.text({ primaryKey: true }), name: State.SQLite.text({ nullable: false }), email: State.SQLite.text({ nullable: false }), age: State.SQLite.integer({ nullable: true }), },})
// Using Effect Schema with annotationsimport { Schema } from '@livestore/utils/effect'
const UserSchema = Schema.Struct({ id: Schema.Int.pipe(State.SQLite.withPrimaryKey).pipe(State.SQLite.withAutoIncrement), email: Schema.String.pipe(State.SQLite.withUnique), name: Schema.String, active: Schema.Boolean.pipe(State.SQLite.withDefault(true)), createdAt: Schema.optional(Schema.Date),})
// Option 1: With explicit nameconst usersTable = State.SQLite.table({ name: 'users', schema: UserSchema,})
// Option 2: With name from schema annotation (title or identifier)const AnnotatedUserSchema = UserSchema.annotations({ 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,}).annotations({ 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}
columns: { id: { columnType: "text"; schema: Schema.Schema<string, string, 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.Schema<string, string, never>; default?: typeof NoDefault; nullable?: false; primaryKey?: true; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false;} (+1 overload)
text({ primaryKey?: true
primaryKey: true }), text: { columnType: "text"; schema: Schema.Schema<string, string, 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.Schema<string, string, never>; default?: ""; nullable?: false; primaryKey?: false; autoIncrement?: false;}) => { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
text({ default?: ""
default: '' }), completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, 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.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false;} (+1 overload)
boolean({ default?: false
default: false }), deletedAt: { columnType: "integer"; schema: Schema.Schema<Date | null, number | null, 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.Schema<Date, number, never>; default?: typeof NoDefault; nullable?: true; primaryKey?: false; autoIncrement?: false;}) => { columnType: "integer"; schema: Schema.Schema<Date | null, number | null, never>; default: None<never>; nullable: true; primaryKey: false; autoIncrement: false;} (+1 overload)
integer({ nullable?: true
nullable: true, schema?: Schema.Schema<Date, number, never>
schema: import Schema
Schema.class DateFromNumber
Defines a schema that converts a number into a Date object using the new Date constructor. This schema does not validate the numerical input,
allowing potentially invalid values such as NaN, Infinity, and
-Infinity to be converted into Date objects. During the encoding process,
any invalid Date object will be encoded to NaN.
DateFromNumber }), }, }),}
export const const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>;}
events = { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>
todoCreated: import Events
Events.synced<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}>(args: { name: "v1.TodoCreated"; schema: Schema.Schema<{ readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly text: string; readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, false>export synced
synced({ name: "v1.TodoCreated"
name: 'v1.TodoCreated', schema: Schema.Schema<{ readonly text: string; readonly id: string;}, { readonly text: string; readonly id: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String; text: typeof Schema.String;}>(fields: { id: typeof Schema.String; text: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.String; text: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String, text: typeof Schema.String
text: import Schema
Schema.class Stringexport String
String }), }), todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}, false>
todoCompleted: import Events
Events.synced<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoCompleted"; schema: Schema.Schema<{ readonly id: string; }, { readonly id: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string;}, { readonly id: string;}, false>export synced
synced({ name: "v1.TodoCompleted"
name: 'v1.TodoCompleted', schema: Schema.Schema<{ readonly id: string;}, { readonly id: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String;}>(fields: { id: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String }), }), todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}, false>
todoUncompleted: import Events
Events.synced<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}>(args: { name: "v1.TodoUncompleted"; schema: Schema.Schema<{ readonly id: string; }, { readonly id: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string;}, { readonly id: string;}, false>export synced
synced({ name: "v1.TodoUncompleted"
name: 'v1.TodoUncompleted', schema: Schema.Schema<{ readonly id: string;}, { readonly id: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String;}>(fields: { id: typeof Schema.String;}): Schema.Struct<{ id: typeof Schema.String;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String }), }), todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, false>
todoDeleted: import Events
Events.synced<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}>(args: { name: "v1.TodoDeleted"; schema: Schema.Schema<{ readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly id: string; readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, false>export synced
synced({ name: "v1.TodoDeleted"
name: 'v1.TodoDeleted', schema: Schema.Schema<{ readonly id: string; readonly deletedAt: Date;}, { readonly id: string; readonly deletedAt: string;}, never>
schema: import Schema
Schema.function Struct<{ id: typeof Schema.String; deletedAt: typeof Schema.Date;}>(fields: { id: typeof Schema.String; deletedAt: typeof Schema.Date;}): Schema.Struct<{ id: typeof Schema.String; deletedAt: typeof Schema.Date;}> (+1 overload)
Struct({ id: typeof Schema.String
id: import Schema
Schema.class Stringexport String
String, deletedAt: typeof Schema.Date
deletedAt: import Schema
Schema.class Dateexport Date
This schema converts a string into a Date object using the new Date
constructor. It ensures that only valid date strings are accepted,
rejecting any strings that would result in an invalid date, such as new Date("Invalid Date").
Date }), }), todoClearedCompleted: State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}, false>
todoClearedCompleted: import Events
Events.synced<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}>(args: { name: "v1.TodoClearedCompleted"; schema: Schema.Schema<{ readonly deletedAt: Date; }, { readonly deletedAt: string; }, never>;} & Omit<State.SQLite.DefineEventOptions<{ readonly deletedAt: Date;}, false>, "derived" | "clientOnly">): State.SQLite.EventDef<"v1.TodoClearedCompleted", { readonly deletedAt: Date;}, { readonly deletedAt: string;}, false>export synced
synced({ name: "v1.TodoClearedCompleted"
name: 'v1.TodoClearedCompleted', schema: Schema.Schema<{ readonly deletedAt: Date;}, { readonly deletedAt: string;}, never>
schema: import Schema
Schema.function Struct<{ deletedAt: typeof Schema.Date;}>(fields: { deletedAt: typeof Schema.Date;}): Schema.Struct<{ deletedAt: typeof Schema.Date;}> (+1 overload)
Struct({ deletedAt: typeof Schema.Date
deletedAt: import Schema
Schema.class Dateexport Date
This schema converts a string into a Date object using the new Date
constructor. It ensures that only valid date strings are accepted,
rejecting any strings that would result in an invalid date, such as new Date("Invalid Date").
Date }), }),}
const const materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>>; "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", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>;}>(_eventDefRecord: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>;}, handlers: { ...;}) => { ...;}
materializers(const events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.insert: (values: { readonly id: string; readonly text?: string; readonly completed?: boolean; readonly deletedAt?: Date | null;}) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Insert a new row into the table
Example:
db.todos.insert({ id: '123', text: 'Buy milk', status: 'active' })
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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.update: (values: Partial<{ readonly text: string; readonly id: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: true }).where: (params: Partial<{ readonly id: string | { op: QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: QueryBuilder.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+2 overloads)
where({ id?: string | { op: QueryBuilder.WhereOps.SingleValue; 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.update: (values: Partial<{ readonly text: string; readonly id: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ completed?: boolean
completed: false }).where: (params: Partial<{ readonly id: string | { op: QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: QueryBuilder.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+2 overloads)
where({ id?: string | { op: QueryBuilder.WhereOps.SingleValue; 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.update: (values: Partial<{ readonly text: string; readonly id: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: string | { op: QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: QueryBuilder.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+2 overloads)
where({ id?: string | { op: QueryBuilder.WhereOps.SingleValue; 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables.todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>
todos.update: (values: Partial<{ readonly text: string; readonly id: string; readonly completed: boolean; readonly deletedAt: Date | null;}>) => QueryBuilder<readonly { readonly id: string; readonly text: string; readonly completed: boolean; readonly deletedAt: Date | null;}[], State.SQLite.TableDefBase<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { ...; }; readonly deletedAt: { ...; };}>, State.SQLite.WithDefaults<...>>, "select" | ... 6 more ... | "row">
Update rows in the table that match the where clause
Example:
db.todos.update({ status: 'completed' }).where({ id: '123' })
update({ deletedAt?: Date | null
deletedAt }).where: (params: Partial<{ readonly id: string | { op: QueryBuilder<TResult, TTableDef extends State.SQLite.TableDefBase, TWithout extends QueryBuilder.ApiFeature = never>.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly text: string | { op: QueryBuilder.WhereOps.SingleValue; value: string; } | { op: QueryBuilder.WhereOps.MultiValue; value: readonly string[]; } | undefined; readonly completed: boolean | ... 2 more ... | undefined; readonly deletedAt: Date | ... 3 more ... | undefined;}>) => QueryBuilder<...> (+2 overloads)
where({ completed?: boolean | { op: QueryBuilder.WhereOps.SingleValue; 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.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; }; materializers: { ...; };}>(inputSchema: { tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>; }; materializers: { ...; };}) => InternalState
makeState({ tables: { todos: State.SQLite.TableDef<State.SQLite.SqliteTableDefForInput<"todos", { readonly id: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: None<never>; nullable: false; primaryKey: true; autoIncrement: false; }; readonly text: { columnType: "text"; schema: Schema.Schema<string, string, never>; default: Some<"">; nullable: false; primaryKey: false; autoIncrement: false; }; readonly completed: { columnType: "integer"; schema: Schema.Schema<boolean, number, never>; default: Some<false>; nullable: false; primaryKey: false; autoIncrement: false; }; readonly deletedAt: { ...; }; }>, State.SQLite.WithDefaults<...>, Schema.Schema<...>>;}
tables, materializers: { "v1.TodoCreated": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>>; "v1.TodoCompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>>; "v1.TodoUncompleted": State.SQLite.Materializer<State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>>; "v1.TodoDeleted": State.SQLite.Materializer<...>; "v1.TodoClearedCompleted": State.SQLite.Materializer<...>;}
materializers })
export const const schema: FromInputSchema.DeriveSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}>
schema = makeSchema<{ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}>(inputSchema: { events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; todoClearedCompleted: State.SQLite.EventDef<...>; }; state: InternalState;}): FromInputSchema.DeriveSchema<...>
makeSchema({ events: { todoCreated: State.SQLite.EventDef<"v1.TodoCreated", { readonly text: string; readonly id: string; }, { readonly text: string; readonly id: string; }, false>; todoCompleted: State.SQLite.EventDef<"v1.TodoCompleted", { readonly id: string; }, { readonly id: string; }, false>; todoUncompleted: State.SQLite.EventDef<"v1.TodoUncompleted", { readonly id: string; }, { readonly id: string; }, false>; todoDeleted: State.SQLite.EventDef<"v1.TodoDeleted", { readonly id: string; readonly deletedAt: Date; }, { readonly id: string; readonly deletedAt: string; }, false>; 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.