Skip to content

Custom Elements

LiveStore can be used with custom elements/web components.

See examples for a complete example.

import {
const makePersistedAdapter: (options: WebAdapterOptions) => Adapter

Creates a web adapter with persistent storage (currently only supports OPFS). Requires both a web worker and a shared worker.

@example

import { makePersistedAdapter } from '@livestore/adapter-web'
import LiveStoreWorker from './livestore.worker.ts?worker'
import LiveStoreSharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'
const adapter = makePersistedAdapter({
worker: LiveStoreWorker,
sharedWorker: LiveStoreSharedWorker,
storage: { type: 'opfs' },
})

makePersistedAdapter
} from '@livestore/adapter-web'
import
const LiveStoreSharedWorker: new (options?: {
name?: string;
}) => SharedWorker
LiveStoreSharedWorker
from '@livestore/adapter-web/shared-worker?sharedworker'
import {
const createStorePromise: <TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TContext = {}, TSyncPayloadSchema extends Schema<any> = Schema<JsonValue, JsonValue, never>>({ signal, otelOptions, ...options }: CreateStoreOptions<TSchema, TContext, TSyncPayloadSchema> & {
signal?: AbortSignal;
otelOptions?: Partial<OtelOptions>;
}) => Promise<Store<TSchema, TContext>>

Create a new LiveStore Store

createStorePromise
,
const queryDb: {
<TResultSchema, TResult = TResultSchema>(queryInput: QueryInputRaw<TResultSchema, ReadonlyArray<any>> | QueryBuilder<TResultSchema, any, any>, options?: {
map?: (rows: TResultSchema) => TResult;
label?: string;
deps?: DepKey;
}): LiveQueryDef<TResult>;
<TResultSchema, TResult = TResultSchema>(queryInput: ((get: GetAtomResult) => QueryInputRaw<TResultSchema, ReadonlyArray<any>>) | ((get: GetAtomResult) => QueryBuilder<TResultSchema, any, any>), options?: {
map?: (rows: TResultSchema) => TResult;
label?: string;
deps?: DepKey;
}): LiveQueryDef<TResult>;
}

NOTE queryDb is only supposed to read data. Don't use it to insert/update/delete data but use events instead.

When using contextual data when constructing the query, please make sure to include it in the deps option.

@example

const todos$ = queryDb(tables.todos.where({ complete: true }))

@example

// Group-by raw SQL query
const colorCounts$ = queryDb({
query: sql`SELECT color, COUNT(*) as count FROM todos WHERE complete = ? GROUP BY color`,
schema: Schema.Array(Schema.Struct({
color: Schema.String,
count: Schema.Number,
})),
bindValues: [1],
})

@example

// Using contextual data when constructing the query
const makeFilteredQuery = (filter: string) =>
queryDb(tables.todos.where({ title: { op: 'like', value: filter } }), { deps: [filter] })
const filteredTodos$ = makeFilteredQuery('buy coffee')

queryDb
} from '@livestore/livestore'
import
const LiveStoreWorker: new (options?: {
name?: string;
}) => Worker
LiveStoreWorker
from './livestore/livestore.worker.ts?worker'
import {
const 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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
}
events
,
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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
};
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<...>>;
uiState: ClientDocumentTableDef<...>;
}
tables
} from './livestore/schema.ts'
const
const adapter: Adapter
adapter
=
function makePersistedAdapter(options: WebAdapterOptions): Adapter

Creates a web adapter with persistent storage (currently only supports OPFS). Requires both a web worker and a shared worker.

@example

import { makePersistedAdapter } from '@livestore/adapter-web'
import LiveStoreWorker from './livestore.worker.ts?worker'
import LiveStoreSharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'
const adapter = makePersistedAdapter({
worker: LiveStoreWorker,
sharedWorker: LiveStoreSharedWorker,
storage: { type: 'opfs' },
})

makePersistedAdapter
({
storage: {
readonly type: "opfs";
readonly directory?: string | undefined;
}

Specifies where to persist data for this adapter

storage
: {
type: "opfs"
type
: 'opfs' },
worker: ((options: {
name: string;
}) => globalThis.Worker) | (new (options: {
name: string;
}) => globalThis.Worker)
worker
:
const LiveStoreWorker: new (options?: {
name?: string;
}) => Worker
LiveStoreWorker
,
sharedWorker: ((options: {
name: string;
}) => globalThis.SharedWorker) | (new (options: {
name: string;
}) => globalThis.SharedWorker)

This is mostly an implementation detail and needed to be exposed into app code due to a current Vite limitation (https://github.com/vitejs/vite/issues/8427).

In most cases this should look like:

import LiveStoreSharedWorker from '@livestore/adapter-web/shared-worker?sharedworker'
const adapter = makePersistedAdapter({
sharedWorker: LiveStoreSharedWorker,
// ...
})

sharedWorker
:
const LiveStoreSharedWorker: new (options?: {
name?: string;
}) => SharedWorker
LiveStoreSharedWorker
,
})
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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
};
state: InternalState;
}>, {}>
store
= await
createStorePromise<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>;
uiStateSet: ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.SetEventDefLike<...>;
};
state: InternalState;
}>, {}, Schema<...>>({ signal, otelOptions, ...options }: CreateStoreOptions<...> & {
...;
}): Promise<...>

Create a new LiveStore Store

createStorePromise
({
CreateStoreOptions<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<...>; uiStateSet: ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.SetEventDefLike<...>; }; state: InternalState; }>, {}, Schema<...>>.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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
};
state: InternalState;
}>
schema
,
CreateStoreOptions<TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Schema<any> = Schema<JsonValue, JsonValue, never>>.adapter: Adapter
adapter
,
CreateStoreOptions<TSchema extends LiveStoreSchema, TContext = {}, TSyncPayloadSchema extends Schema<any> = Schema<JsonValue, JsonValue, never>>.storeId: string
storeId
: 'custom-elements-demo' })
const
const visibleTodos$: LiveQueryDef<readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[], "def">
visibleTodos$
=
queryDb<readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[], readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]>(queryInput: QueryInputRaw<readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[], readonly any[]> | QueryBuilder<readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[], any, any>, options?: {
...;
} | undefined): LiveQueryDef<...> (+1 overload)

NOTE queryDb is only supposed to read data. Don't use it to insert/update/delete data but use events instead.

When using contextual data when constructing the query, please make sure to include it in the deps option.

@example

const todos$ = queryDb(tables.todos.where({ complete: true }))

@example

// Group-by raw SQL query
const colorCounts$ = queryDb({
query: sql`SELECT color, COUNT(*) as count FROM todos WHERE complete = ? GROUP BY color`,
schema: Schema.Array(Schema.Struct({
color: Schema.String,
count: Schema.Number,
})),
bindValues: [1],
})

@example

// Using contextual data when constructing the query
const makeFilteredQuery = (filter: string) =>
queryDb(tables.todos.where({ title: { op: 'like', value: filter } }), { deps: [filter] })
const filteredTodos$ = makeFilteredQuery('buy coffee')

queryDb
(
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<...>>;
uiState: ClientDocumentTableDef<...>;
}
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<...>>
todos
.
where: (params: Partial<{
readonly id: string | {
op: QueryBuilder<TResult, TTableDef extends 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
({
deletedAt?: Date | {
op: QueryBuilder.WhereOps.SingleValue;
value: Date | null;
} | {
op: QueryBuilder.WhereOps.MultiValue;
value: readonly (Date | null)[];
} | null | undefined
deletedAt
: null }))
class
class TodoListElement
TodoListElement
extends
var HTMLElement: {
new (): HTMLElement;
prototype: HTMLElement;
}

The HTMLElement interface represents any HTML element.

MDN Reference

HTMLElement
{
private
TodoListElement.list: HTMLUListElement
list
:
interface HTMLUListElement

The HTMLUListElement interface provides special properties (beyond those defined on the regular HTMLElement interface it also has available to it by inheritance) for manipulating unordered list (ul) elements.

MDN Reference

HTMLUListElement
private
TodoListElement.input: HTMLInputElement
input
:
interface HTMLInputElement

The HTMLInputElement interface provides special properties and methods for manipulating the options, layout, and presentation of input elements.

MDN Reference

HTMLInputElement
constructor() {
super()
const
const shadow: ShadowRoot
shadow
= this.
Element.attachShadow(init: ShadowRootInit): ShadowRoot

The Element.attachShadow() method attaches a shadow DOM tree to the specified element and returns a reference to its ShadowRoot.

MDN Reference

attachShadow
({
ShadowRootInit.mode: ShadowRootMode
mode
: 'open' })
this.
TodoListElement.input: HTMLInputElement
input
=
var document: Document

window.document returns a reference to the document contained in the window.

MDN Reference

document
.
Document.createElement<"input">(tagName: "input", options?: ElementCreationOptions): HTMLInputElement (+2 overloads)

In an HTML document, the document.createElement() method creates the HTML element specified by localName, or an HTMLUnknownElement if localName isn't recognized.

MDN Reference

createElement
('input')
this.
TodoListElement.input: HTMLInputElement
input
.
HTMLInputElement.placeholder: string

The placeholder property of the HTMLInputElement interface represents a hint to the user of what can be entered in the control.

MDN Reference

placeholder
= 'What needs to be done?'
this.
TodoListElement.list: HTMLUListElement
list
=
var document: Document

window.document returns a reference to the document contained in the window.

MDN Reference

document
.
Document.createElement<"ul">(tagName: "ul", options?: ElementCreationOptions): HTMLUListElement (+2 overloads)

In an HTML document, the document.createElement() method creates the HTML element specified by localName, or an HTMLUnknownElement if localName isn't recognized.

MDN Reference

createElement
('ul')
this.
TodoListElement.list: HTMLUListElement
list
.
ElementCSSInlineStyle.style: CSSStyleDeclaration
style
.
CSSStyleDeclaration.listStyle: string
listStyle
= 'none'
this.
TodoListElement.list: HTMLUListElement
list
.
ElementCSSInlineStyle.style: CSSStyleDeclaration
style
.
CSSStyleDeclaration.padding: string
padding
= '0'
this.
TodoListElement.list: HTMLUListElement
list
.
ElementCSSInlineStyle.style: CSSStyleDeclaration
style
.
CSSStyleDeclaration.margin: string
margin
= '16px 0 0'
this.
TodoListElement.input: HTMLInputElement
input
.
HTMLInputElement.addEventListener<"keydown">(type: "keydown", listener: (this: HTMLInputElement, ev: KeyboardEvent) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)

The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.

MDN Reference

Adds a new handler for the type event. Any given listener is added only once per type and per capture option value.

If the once option is true, the listener is removed after the next time a type event is dispatched.

The capture option is not used by Node.js in any functional way other than tracking registered event listeners per the EventTarget specification. Specifically, the capture option is used as part of the key when registering a listener. Any individual listener may be added once with capture = false, and once with capture = true.

The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.

MDN Reference

Adds a new handler for the type event. Any given listener is added only once per type and per capture option value.

If the once option is true, the listener is removed after the next time a type event is dispatched.

The capture option is not used by Node.js in any functional way other than tracking registered event listeners per the EventTarget specification. Specifically, the capture option is used as part of the key when registering a listener. Any individual listener may be added once with capture = false, and once with capture = true.

addEventListener
('keydown', (
event: KeyboardEvent
event
) => {
if (
event: KeyboardEvent
event
.
KeyboardEvent.key: string

The KeyboardEvent interface's key read-only property returns the value of the key pressed by the user, taking into consideration the state of modifier keys such as Shift as well as the keyboard locale and layout.

MDN Reference

key
=== 'Enter' && this.
TodoListElement.input: HTMLInputElement
input
.
HTMLInputElement.value: string

The value property of the HTMLInputElement interface represents the current value of the input element as a string.

MDN Reference

value
.
String.trim(): string

Removes the leading and trailing white space and line terminator characters from a string.

trim
()) {
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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
};
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<...>; uiStateSet: ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.SetEventDefLike<...>; }; state: InternalState; }>, {}>.commit: <readonly [{
name: "v1.TodoCreated";
args: {
readonly id: string;
readonly text: string;
};
}]>(list_0: {
name: "v1.TodoCreated";
args: {
readonly id: string;
readonly text: string;
};
}) => void (+3 overloads)
commit
(
const 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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
}
events
.
todoCreated: (args: {
readonly id: string;
readonly text: string;
}) => {
name: "v1.TodoCreated";
args: {
readonly id: string;
readonly text: string;
};
}

Helper function to construct a partial event

todoCreated
({
id: string
id
:
var crypto: Crypto
crypto
.
Crypto.randomUUID(): `${string}-${string}-${string}-${string}-${string}` (+1 overload)
randomUUID
(),
text: string
text
: this.
TodoListElement.input: HTMLInputElement
input
.
HTMLInputElement.value: string

The value property of the HTMLInputElement interface represents the current value of the input element as a string.

MDN Reference

value
.
String.trim(): string

Removes the leading and trailing white space and line terminator characters from a string.

trim
() }))
this.
TodoListElement.input: HTMLInputElement
input
.
HTMLInputElement.value: string

The value property of the HTMLInputElement interface represents the current value of the input element as a string.

MDN Reference

value
= ''
}
})
const shadow: ShadowRoot
shadow
.
ParentNode.append(...nodes: (Node | string)[]): void

Inserts nodes after the last child of node, while replacing strings in nodes with equivalent Text nodes.

Throws a "HierarchyRequestError" DOMException if the constraints of the node tree are violated.

MDN Reference

append
(this.
TodoListElement.input: HTMLInputElement
input
, this.
TodoListElement.list: HTMLUListElement
list
)
}
TodoListElement.connectedCallback(): void
connectedCallback
(): void {
this.
TodoListElement.renderTodos(todos: ReadonlyArray<typeof tables.todos.Type>): void
renderTodos
(
var Array: ArrayConstructor
Array
.
ArrayConstructor.from<{
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}>(iterable: Iterable<{
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}> | ArrayLike<{
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}>): {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[] (+3 overloads)

Creates an array from an iterable object.

@paramiterable An iterable object to convert to an array.

from
(
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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
};
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<...>; uiStateSet: ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.SetEventDefLike<...>; }; state: InternalState; }>, {}>.query: <readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]>(query: Queryable<readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]> | {
query: string;
bindValues: Bindable;
schema?: Schema<readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[], readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[], never>;
}, options?: {
otelContext?: Context;
debugRefreshReason?: RefreshReason;
}) => readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]

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
(
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<...>>;
uiState: ClientDocumentTableDef<...>;
}
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<...>>
todos
.
where: (params: Partial<{
readonly id: string | {
op: QueryBuilder<TResult, TTableDef extends 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
({
deletedAt?: Date | {
op: QueryBuilder.WhereOps.SingleValue;
value: Date | null;
} | {
op: QueryBuilder.WhereOps.MultiValue;
value: readonly (Date | null)[];
} | null | undefined
deletedAt
: null }))))
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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
};
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<...>; uiStateSet: ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.SetEventDefLike<...>; }; state: InternalState; }>, {}>.subscribe: <readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]>(query: Queryable<readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]>, onUpdate: (value: readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]) => void, options?: SubscribeOptions<readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]> | undefined) => Unsubscribe (+1 overload)
subscribe
(
const visibleTodos$: LiveQueryDef<readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[], "def">
visibleTodos$
, (
todos: readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]
todos
) => this.
TodoListElement.renderTodos(todos: ReadonlyArray<typeof tables.todos.Type>): void
renderTodos
(
todos: readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]
todos
))
}
private
TodoListElement.renderTodos(todos: ReadonlyArray<typeof tables.todos.Type>): void
renderTodos
(
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: {
columnType: "integer";
... 4 more ...;
autoIncrement: false;
};
}>, WithDefaults<...>, Schema<...>>;
uiState: ClientDocumentTableDef<...>;
}
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<...>>
todos
.
type Type: {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}
Type
>): void {
const
const nodes: HTMLLIElement[]
nodes
=
var Array: ArrayConstructor
Array
.
ArrayConstructor.from<{
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}, HTMLLIElement>(iterable: Iterable<{
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}> | ArrayLike<{
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}>, mapfn: (v: {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}, k: number) => HTMLLIElement, thisArg?: any): HTMLLIElement[] (+3 overloads)

Creates an array from an iterable object.

@paramiterable An iterable object to convert to an array.

@parammapfn A mapping function to call on every element of the array.

@paramthisArg Value of 'this' used to invoke the mapfn.

from
(
todos: readonly {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}[]
todos
, (
todo: {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}
todo
) => {
const
const item: HTMLLIElement
item
=
var document: Document

window.document returns a reference to the document contained in the window.

MDN Reference

document
.
Document.createElement<"li">(tagName: "li", options?: ElementCreationOptions): HTMLLIElement (+2 overloads)

In an HTML document, the document.createElement() method creates the HTML element specified by localName, or an HTMLUnknownElement if localName isn't recognized.

MDN Reference

createElement
('li')
const item: HTMLLIElement
item
.
Element.textContent: string | null
textContent
=
todo: {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}
todo
.
text: string
text
const item: HTMLLIElement
item
.
ElementCSSInlineStyle.style: CSSStyleDeclaration
style
.
CSSStyleDeclaration.cursor: string
cursor
= 'pointer'
const item: HTMLLIElement
item
.
HTMLLIElement.addEventListener<"click">(type: "click", listener: (this: HTMLLIElement, ev: PointerEvent) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)

The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.

MDN Reference

Adds a new handler for the type event. Any given listener is added only once per type and per capture option value.

If the once option is true, the listener is removed after the next time a type event is dispatched.

The capture option is not used by Node.js in any functional way other than tracking registered event listeners per the EventTarget specification. Specifically, the capture option is used as part of the key when registering a listener. Any individual listener may be added once with capture = false, and once with capture = true.

The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.

MDN Reference

Adds a new handler for the type event. Any given listener is added only once per type and per capture option value.

If the once option is true, the listener is removed after the next time a type event is dispatched.

The capture option is not used by Node.js in any functional way other than tracking registered event listeners per the EventTarget specification. Specifically, the capture option is used as part of the key when registering a listener. Any individual listener may be added once with capture = false, and once with capture = true.

addEventListener
('click', () => {
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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
};
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<...>; uiStateSet: ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.SetEventDefLike<...>; }; state: InternalState; }>, {}>.commit: <readonly [{
name: "v1.TodoCompleted";
args: {
readonly id: string;
};
} | {
name: "v1.TodoUncompleted";
args: {
readonly id: string;
};
}]>(list_0: {
name: "v1.TodoCompleted";
args: {
readonly id: string;
};
} | {
name: "v1.TodoUncompleted";
args: {
readonly id: string;
};
}) => void (+3 overloads)
commit
(
todo: {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}
todo
.
completed: boolean
completed
?
const 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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
}
events
.
todoUncompleted: (args: {
readonly id: string;
}) => {
name: "v1.TodoUncompleted";
args: {
readonly id: string;
};
}

Helper function to construct a partial event

todoUncompleted
({
id: string
id
:
todo: {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}
todo
.
id: string
id
}) :
const 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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
}
events
.
todoCompleted: (args: {
readonly id: string;
}) => {
name: "v1.TodoCompleted";
args: {
readonly id: string;
};
}

Helper function to construct a partial event

todoCompleted
({
id: string
id
:
todo: {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}
todo
.
id: string
id
}))
})
const
const deleteButton: HTMLButtonElement
deleteButton
=
var document: Document

window.document returns a reference to the document contained in the window.

MDN Reference

document
.
Document.createElement<"button">(tagName: "button", options?: ElementCreationOptions): HTMLButtonElement (+2 overloads)

In an HTML document, the document.createElement() method creates the HTML element specified by localName, or an HTMLUnknownElement if localName isn't recognized.

MDN Reference

createElement
('button')
const deleteButton: HTMLButtonElement
deleteButton
.
HTMLButtonElement.type: "button" | "reset" | "submit"

The type property of the HTMLButtonElement interface is a string that indicates the behavior type of the button element.

MDN Reference

type
= 'button'
const deleteButton: HTMLButtonElement
deleteButton
.
Element.textContent: string | null
textContent
= '✕'
const deleteButton: HTMLButtonElement
deleteButton
.
ElementCSSInlineStyle.style: CSSStyleDeclaration
style
.
CSSStyleDeclaration.marginLeft: string
marginLeft
= '8px'
const deleteButton: HTMLButtonElement
deleteButton
.
HTMLButtonElement.addEventListener<"click">(type: "click", listener: (this: HTMLButtonElement, ev: PointerEvent) => any, options?: boolean | AddEventListenerOptions): void (+1 overload)

The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.

MDN Reference

Adds a new handler for the type event. Any given listener is added only once per type and per capture option value.

If the once option is true, the listener is removed after the next time a type event is dispatched.

The capture option is not used by Node.js in any functional way other than tracking registered event listeners per the EventTarget specification. Specifically, the capture option is used as part of the key when registering a listener. Any individual listener may be added once with capture = false, and once with capture = true.

The addEventListener() method of the EventTarget interface sets up a function that will be called whenever the specified event is delivered to the target.

MDN Reference

Adds a new handler for the type event. Any given listener is added only once per type and per capture option value.

If the once option is true, the listener is removed after the next time a type event is dispatched.

The capture option is not used by Node.js in any functional way other than tracking registered event listeners per the EventTarget specification. Specifically, the capture option is used as part of the key when registering a listener. Any individual listener may be added once with capture = false, and once with capture = true.

addEventListener
('click', (
event: PointerEvent
event
) => {
event: PointerEvent
event
.
Event.stopPropagation(): void (+1 overload)

This is not used in Node.js and is provided purely for completeness.

stopPropagation
()
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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
};
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<...>; uiStateSet: ClientDocumentTableDef<TName extends string, TType, TEncoded, TOptions extends ClientDocumentTableOptions<TType>>.SetEventDefLike<...>; }; state: InternalState; }>, {}>.commit: <readonly [{
name: "v1.TodoDeleted";
args: {
readonly id: string;
readonly deletedAt: Date;
};
}]>(list_0: {
name: "v1.TodoDeleted";
args: {
readonly id: string;
readonly deletedAt: Date;
};
}) => void (+3 overloads)
commit
(
const 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>;
uiStateSet: ClientDocumentTableDef.SetEventDefLike<...>;
}
events
.
todoDeleted: (args: {
readonly id: string;
readonly deletedAt: Date;
}) => {
name: "v1.TodoDeleted";
args: {
readonly id: string;
readonly deletedAt: Date;
};
}

Helper function to construct a partial event

todoDeleted
({
id: string
id
:
todo: {
readonly id: string;
readonly text: string;
readonly completed: boolean;
readonly deletedAt: Date | null;
}
todo
.
id: string
id
,
deletedAt: Date
deletedAt
: new
var Date: DateConstructor
new () => Date (+3 overloads)
Date
() }))
})
const
const row: HTMLDivElement
row
=
var document: Document

window.document returns a reference to the document contained in the window.

MDN Reference

document
.
Document.createElement<"div">(tagName: "div", options?: ElementCreationOptions): HTMLDivElement (+2 overloads)

In an HTML document, the document.createElement() method creates the HTML element specified by localName, or an HTMLUnknownElement if localName isn't recognized.

MDN Reference

createElement
('div')
const row: HTMLDivElement
row
.
ElementCSSInlineStyle.style: CSSStyleDeclaration
style
.
CSSStyleDeclaration.display: string
display
= 'flex'
const row: HTMLDivElement
row
.
ElementCSSInlineStyle.style: CSSStyleDeclaration
style
.
CSSStyleDeclaration.alignItems: string
alignItems
= 'center'
const row: HTMLDivElement
row
.
Node.appendChild<HTMLLIElement>(node: HTMLLIElement): HTMLLIElement

The appendChild() method of the Node interface adds a node to the end of the list of children of a specified parent node.

MDN Reference

appendChild
(
const item: HTMLLIElement
item
)
const row: HTMLDivElement
row
.
Node.appendChild<HTMLButtonElement>(node: HTMLButtonElement): HTMLButtonElement

The appendChild() method of the Node interface adds a node to the end of the list of children of a specified parent node.

MDN Reference

appendChild
(
const deleteButton: HTMLButtonElement
deleteButton
)
const
const wrapper: HTMLLIElement
wrapper
=
var document: Document

window.document returns a reference to the document contained in the window.

MDN Reference

document
.
Document.createElement<"li">(tagName: "li", options?: ElementCreationOptions): HTMLLIElement (+2 overloads)

In an HTML document, the document.createElement() method creates the HTML element specified by localName, or an HTMLUnknownElement if localName isn't recognized.

MDN Reference

createElement
('li')
const wrapper: HTMLLIElement
wrapper
.
Node.appendChild<HTMLDivElement>(node: HTMLDivElement): HTMLDivElement

The appendChild() method of the Node interface adds a node to the end of the list of children of a specified parent node.

MDN Reference

appendChild
(
const row: HTMLDivElement
row
)
return
const wrapper: HTMLLIElement
wrapper
})
this.
TodoListElement.list: HTMLUListElement
list
.
ParentNode.replaceChildren(...nodes: (Node | string)[]): void

Replace all children of node with nodes, while replacing strings in nodes with equivalent Text nodes.

Throws a "HierarchyRequestError" DOMException if the constraints of the node tree are violated.

MDN Reference

replaceChildren
(...
const nodes: HTMLLIElement[]
nodes
)
}
}
var customElements: CustomElementRegistry

The customElements read-only property of the Window interface returns a reference to the CustomElementRegistry object, which can be used to register new custom elements and get information about previously registered custom elements.

MDN Reference

customElements
.
CustomElementRegistry.define(name: string, constructor: CustomElementConstructor, options?: ElementDefinitionOptions): void

The define() method of the CustomElementRegistry interface adds a definition for a custom element to the custom element registry, mapping its name to the constructor which will be used to create it.

MDN Reference

define
('todo-list',
class TodoListElement
TodoListElement
)