import { InitialQueryBuilder, QueryBuilder } from './builder/index.js'; import { Context } from './builder/types.js'; /** Event types for query result deltas */ export type DeltaType = 'enter' | 'exit' | 'update'; /** Delta event emitted when a row enters, exits, or updates within a query result */ export type DeltaEvent, TKey extends string | number = string | number> = { type: 'enter'; key: TKey; /** Current value for the entering row */ value: TRow; metadata?: Record; } | { type: 'exit'; key: TKey; /** Current value for the exiting row */ value: TRow; metadata?: Record; } | { type: 'update'; key: TKey; /** Current value after the update */ value: TRow; /** Previous value before the batch */ previousValue: TRow; metadata?: Record; }; /** Context passed to effect handlers */ export interface EffectContext { /** ID of this effect (auto-generated if not provided) */ effectId: string; /** Aborted when effect.dispose() is called */ signal: AbortSignal; } /** Query input - can be a builder function or a prebuilt query */ export type EffectQueryInput = ((q: InitialQueryBuilder) => QueryBuilder) | QueryBuilder; type EffectEventHandler, TKey extends string | number = string | number> = (event: DeltaEvent, ctx: EffectContext) => void | Promise; type EffectBatchHandler, TKey extends string | number = string | number> = (events: Array>, ctx: EffectContext) => void | Promise; /** Effect configuration */ export interface EffectConfig, TKey extends string | number = string | number> { /** Optional ID for debugging/tracing */ id?: string; /** Query to watch for deltas */ query: EffectQueryInput; /** Called once for each row entering the query result */ onEnter?: EffectEventHandler; /** Called once for each row updating within the query result */ onUpdate?: EffectEventHandler; /** Called once for each row exiting the query result */ onExit?: EffectEventHandler; /** Called once per graph run with all delta events from that batch */ onBatch?: EffectBatchHandler; /** Error handler for exceptions thrown by effect callbacks */ onError?: (error: Error, event: DeltaEvent) => void; /** * Called when a source collection enters an error or cleaned-up state. * The effect is automatically disposed after this callback fires. * If not provided, the error is logged to console.error. */ onSourceError?: (error: Error) => void; /** * Skip deltas during initial collection load. * Defaults to false (process all deltas including initial sync). * Set to true for effects that should only process new changes. */ skipInitial?: boolean; } /** Handle returned by createEffect */ export interface Effect { /** Dispose the effect. Returns a promise that resolves when in-flight handlers complete. */ dispose: () => Promise; /** Whether this effect has been disposed */ readonly disposed: boolean; } /** * Creates a reactive effect that fires handlers when rows enter, exit, or * update within a query result. Effects process deltas only — they do not * maintain or require the full materialised query result. * * @example * ```typescript * const effect = createEffect({ * query: (q) => q.from({ msg: messagesCollection }) * .where(({ msg }) => eq(msg.role, 'user')), * onEnter: async (event) => { * await generateResponse(event.value) * }, * }) * * // Later: stop the effect * await effect.dispose() * ``` */ export declare function createEffect, TKey extends string | number = string | number>(config: EffectConfig): Effect; export {};