import type * as otel from '@opentelemetry/api'; import { Equal, Hash } from '@livestore/utils/effect'; import * as RG from '../reactive.ts'; import type { QueryDebugInfo, RefreshReason } from '../store/store-types.ts'; import type { Store } from '../store/store.ts'; import type { StackInfo } from '../utils/stack-info.ts'; export type ReactivityGraph = RG.ReactiveGraph; export declare const makeReactivityGraph: () => ReactivityGraph; export type ReactivityGraphContext = { store: Store; /** Maps from the hash of the query definition to the RcRef of the query */ defRcMap: Map>>; /** Back-reference to the reactivity graph for convenience */ reactivityGraph: WeakRef; otelTracer: otel.Tracer; rootOtelContext: otel.Context; effectsWrapper: (run: () => void) => void; }; export type GetResult> = TQuery extends LiveQuery ? TResult : TQuery extends LiveQueryDef ? TResult : TQuery extends SignalDef ? TResult : unknown; /** * A signal definition representing ephemeral, local-only reactive state. * * `SignalDef` is the type returned by {@link signal}. It's a blueprint for creating * signal instances—the actual instance is created when you use the definition with * a Store via `store.query()` or `store.setSignal()`. * * @typeParam T - The type of value the signal holds */ export interface SignalDef extends LiveQueryDef { _tag: 'signal-def'; /** The initial value used when the signal is first created */ defaultValue: T; /** Unique identifier for caching and deduplication */ hash: string; /** Human-readable label for debugging and devtools */ label: string; /** Creates a reference-counted signal instance bound to a Store's reactivity graph */ make: (ctx: ReactivityGraphContext) => RcRef>; [Equal.symbol](that: SignalDef): boolean; [Hash.symbol](): number; } /** * Interface for a live signal instance. * * This represents an active signal bound to a Store's reactivity graph. * Use `store.setSignal()` to update values and `store.query()` to read them. * * @typeParam T - The type of value the signal holds */ export interface ISignal extends LiveQuery { _tag: 'signal'; reactivityGraph: ReactivityGraph; /** The underlying reactive reference in the graph */ ref: RG.Ref; /** Sets the signal's value (prefer using `store.setSignal()` instead) */ set: (value: T) => void; /** Gets the signal's current value (prefer using `store.query()` instead) */ get: () => T; /** Removes the signal from the reactivity graph */ destroy: () => void; } export declare const TypeId: unique symbol; export type TypeId = typeof TypeId; /** * A reference-counted wrapper around a LiveQuery or Signal instance. * * LiveStore uses reference counting to manage query lifecycle. When multiple * components or subscriptions use the same query definition, they share a single * instance. The instance is destroyed when the last reference is released. * * You typically don't interact with `RcRef` directly—it's used internally by * hooks like `useQuery` and `useQueryRef`. */ export interface RcRef { /** Current reference count */ rc: number; /** The wrapped query or signal instance */ value: T; /** Decrements the reference count; destroys the instance when it reaches zero */ deref: () => void; } /** * Dependency key used to identify queries on platforms where `fn.toString()` isn't reliable. * * On Expo/React Native, Hermes compiles functions to bytecode, so `fn.toString()` returns * `[native code]`. To uniquely identify contextual queries, you must provide explicit `deps`. * * @example * ```ts * // On Expo, this would fail without deps: * const filtered$ = queryDb( * (get) => tables.todos.where({ userId: get(userId$) }), * { deps: [userId] } // Required on Expo/React Native * ) * ``` */ export type DepKey = string | number | ReadonlyArray; export declare const depsToString: (deps: DepKey) => string; /** * A query definition representing a blueprint for a reactive query. * * Query definitions are created by {@link queryDb}, {@link computed}, and {@link signal}. * They're lightweight and can be defined at module scope. The actual query instance * (which holds state) is created lazily when you use the definition with a Store. * * Multiple uses of the same definition share a single instance via reference counting. * * @typeParam TResult - The type of value the query returns * @typeParam TTag - Internal discriminator tag ('def' for queries, 'signal-def' for signals) */ export interface LiveQueryDef { _tag: TTag; /** Creates a reference-counted query instance bound to a Store's reactivity graph */ make: (ctx: ReactivityGraphContext, otelContext?: otel.Context) => RcRef | ISignal>; /** Human-readable label for debugging and devtools */ label: string; /** Unique identifier derived from the query string or explicit deps; used for caching */ hash: string; [Equal.symbol](that: LiveQueryDef): boolean; [Hash.symbol](): number; } export declare namespace LiveQueryDef { type Any = LiveQueryDef; } /** * A live query instance bound to a specific Store. * * `LiveQuery` represents an active, stateful query in the reactivity graph. Unlike * query definitions (`LiveQueryDef`), instances maintain state like execution counts, * timing data, and active subscriptions. * * You typically don't work with `LiveQuery` directly—use `store.query()` for one-shot * reads or `store.subscribe()` for reactive subscriptions. The instance is managed * automatically via reference counting. * * @typeParam TResult - The type of value the query returns */ export interface LiveQuery { /** Unique identifier for this query instance */ id: number; /** Discriminator for the query type */ _tag: 'computed' | 'db' | 'graphql' | 'signal'; [TypeId]: TypeId; /** Type-level only—extracts the result type from a LiveQuery */ '__result!': TResult; /** The underlying reactive atom in the graph that holds the query result */ results$: RG.Atom; /** Human-readable label for debugging and devtools */ label: string; /** Executes the query and returns the result */ run: (args: { otelContext?: otel.Context; debugRefreshReason?: RefreshReason; }) => TResult; /** Removes the query from the reactivity graph */ destroy: () => void; /** Whether this query instance has been destroyed */ isDestroyed: boolean; /** Stack traces of active subscriptions (for debugging) */ activeSubscriptions: Set; /** Number of times this query has been executed */ runs: number; /** Execution times in milliseconds (for performance monitoring) */ executionTimes: number[]; /** The definition that created this instance */ def: LiveQueryDef | SignalDef; } export declare namespace LiveQuery { type Any = LiveQuery; } export declare abstract class LiveStoreQueryBase implements LiveQuery { '__result!': TResult; id: number; [TypeId]: TypeId; abstract _tag: 'computed' | 'db' | 'graphql' | 'signal'; /** Human-readable label for the query for debugging */ abstract label: string; abstract def: LiveQueryDef | SignalDef; abstract results$: RG.Atom; activeSubscriptions: Set; abstract readonly reactivityGraph: ReactivityGraph; get runs(): number; executionTimes: number[]; isDestroyed: boolean; abstract destroy: () => void; run: (args: { otelContext?: otel.Context; debugRefreshReason?: RefreshReason; }) => TResult; protected dependencyQueriesRef: DependencyQueriesRef; } /** * Function signature for the `get` parameter in `computed()` and `queryDb()` callbacks. * * Call `get()` with a query definition, signal, or live query instance to: * 1. Read its current value * 2. Establish a reactive dependency (the caller re-runs when the dependency changes) * * @example * ```ts * const filtered$ = computed((get) => { * const todos = get(todos$) // Depends on todos$ * const filter = get(filterText$) // Depends on filterText$ * return todos.filter((t) => t.text.includes(filter)) * }) * ``` */ export type GetAtomResult = (atom: RG.Atom | LiveQueryDef | LiveQuery | ISignal | SignalDef, otelContext?: otel.Context, debugRefreshReason?: RefreshReason) => T; export type DependencyQueriesRef = Set>>; export declare const makeGetAtomResult: (get: RG.GetAtom, ctx: ReactivityGraphContext, otelContext: otel.Context, dependencyQueriesRef: DependencyQueriesRef) => GetAtomResult; export declare const withRCMap: >(id: string, make: (ctx: ReactivityGraphContext, otelContext?: otel.Context) => T) => ((ctx: ReactivityGraphContext, otelContext?: otel.Context) => RcRef); //# sourceMappingURL=base-class.d.ts.map