/** * Core watch() implementation for reactive queries. * * Creates a Stream that emits result sets whenever the underlying collection data changes. * Subscribes to the PubSub for change notifications, filters events by collection name, * re-evaluates the query pipeline on each change, deduplicates identical consecutive results, * and emits the new result set. */ import { Effect, type PubSub, type Ref, type Scope, Stream } from "effect"; import type { ChangeEvent } from "../types/reactive-types.js"; import { type EvaluateQueryConfig } from "./evaluate-query.js"; /** * Configuration for the watch query. * Extends EvaluateQueryConfig with debounce options. */ export interface WatchQueryConfig extends EvaluateQueryConfig { /** * Debounce interval in milliseconds for change event processing. * When multiple mutations occur in rapid succession, they are coalesced * into a single re-evaluation after the debounce interval settles. * Default: 10ms (fast enough for interactive use, long enough to batch bursts). */ readonly debounceMs?: number; } /** * Entity constraint: must have a readonly string `id` field. */ type HasId = { readonly id: string; }; /** * Creates a reactive watch stream that emits query results whenever the collection changes. * * The stream: * 1. Emits the current result set immediately upon subscription * 2. Subscribes to the PubSub for change notifications (scoped - auto-cleanup) * 3. Filters events to only those matching the specified collection * 4. Debounces change events to coalesce rapid mutations into single re-evaluations * 5. Re-evaluates the query pipeline on each relevant change * 6. Deduplicates consecutive identical result sets to avoid spurious emissions * 7. Emits the new result set as a ReadonlyArray * * Resource management: * - Uses Effect.acquireRelease to manage the PubSub subscription lifecycle * - Subscription is acquired when the watch Effect runs and released when: * - The enclosing Scope closes, OR * - The stream is interrupted/completes (via Stream.ensuring) * - This ensures no memory leaks from lingering subscriptions * * @param pubsub - The PubSub broadcasting ChangeEvents from mutations * @param ref - The collection Ref containing entities keyed by ID * @param collectionName - Name of the collection to watch (for filtering events) * @param config - Optional query configuration (where, sort, select, limit, offset, debounceMs) * @returns Scoped Effect producing a Stream of result arrays * * @example * ```ts * const program = Effect.gen(function* () { * const pubsub = yield* createChangePubSub() * const ref = yield* createCollectionState([]) * * const stream = yield* watch(pubsub, ref, "books", { * where: { genre: "sci-fi" }, * sort: { year: "desc" }, * limit: 10, * debounceMs: 50, // custom debounce interval * }) * * // Consume the stream * yield* Stream.runForEach(stream, (results) => * Effect.log(`Got ${results.length} results`) * ) * }).pipe(Effect.scoped) * ``` */ export declare const watch: (pubsub: PubSub.PubSub, ref: Ref.Ref>, collectionName: string, config?: WatchQueryConfig) => Effect.Effect>, never, Scope.Scope>; export {}; //# sourceMappingURL=watch.d.ts.map