/** * Reactive effect scopes for grouped disposal. * * An `EffectScope` collects all effects, computed values, and watches created * inside its `run()` callback so they can be disposed together with a single * `stop()` call. Scopes nest — an inner scope is collected by its parent. * * @module bquery/reactive */ import type { CleanupFn } from './internals'; /** * A scope that collects reactive resources for grouped disposal. * * @example * ```ts * import { effectScope, signal, effect, computed } from '@bquery/bquery/reactive'; * * const scope = effectScope(); * * scope.run(() => { * const count = signal(0); * effect(() => console.log(count.value)); * const doubled = computed(() => count.value * 2); * }); * * scope.stop(); // All effects and computed values disposed * ``` */ export interface EffectScope { /** Whether the scope has not yet been stopped. */ readonly active: boolean; /** * Executes `fn` inside this scope, collecting any reactive resources * (effects, computed values, watches, nested scopes) created during the call. * * `run()` is synchronous-only. Do not pass an async function or a function * that returns a Promise — resources created after an `await` cannot be * collected reliably. * * @template T - Return type of the provided function * @param fn - Function to run inside the scope * @returns The return value of `fn` * @throws {Error} If the scope has already been stopped */ run(fn: () => T): T; /** * Disposes all collected resources and marks the scope as inactive. * Calling `stop()` on an already-stopped scope is a safe no-op. */ stop(): void; } /** @internal */ export declare const hasScopeDisposer: (scope: EffectScope | undefined) => scope is EffectScope & { _addDisposer(fn: CleanupFn): void; }; /** * Returns the currently active scope, or `undefined` if none. * @internal */ export declare const getActiveScope: () => EffectScope | undefined; /** * Creates a new effect scope for grouped disposal of reactive resources. * * All `effect()`, `computed()`, `watch()`, and nested `effectScope()` calls * made inside `scope.run(fn)` are automatically collected. Calling * `scope.stop()` disposes them all at once. * * `run()` is synchronous-only. Create the scope outside async flows when * needed, but keep the callback itself synchronous so cleanup registration * stays deterministic. * * @returns A new {@link EffectScope} * * @example * ```ts * import { effectScope, signal, effect, onScopeDispose } from '@bquery/bquery/reactive'; * * const scope = effectScope(); * * scope.run(() => { * const count = signal(0); * * effect(() => console.log(count.value)); * * onScopeDispose(() => { * console.log('Custom cleanup'); * }); * }); * * scope.stop(); // logs "Custom cleanup", all effects stopped * ``` */ export declare const effectScope: () => EffectScope; /** * Returns the currently active {@link EffectScope}, or `undefined` if * code is not running inside any scope's `run()` callback. * * @returns The active scope, or `undefined` * * @example * ```ts * import { effectScope, getCurrentScope } from '@bquery/bquery/reactive'; * * const scope = effectScope(); * scope.run(() => { * console.log(getCurrentScope() !== undefined); // true * }); * * console.log(getCurrentScope()); // undefined * ``` */ export declare const getCurrentScope: () => EffectScope | undefined; /** * Registers a cleanup callback on the currently active scope. * * The callback runs when the scope is stopped. This is useful for * registering arbitrary cleanup (e.g. event listeners, timers) * alongside effects and computed values. * * @param fn - Cleanup function to run when the scope stops * @throws {Error} If called outside an active scope * * @example * ```ts * import { effectScope, onScopeDispose } from '@bquery/bquery/reactive'; * * const scope = effectScope(); * * scope.run(() => { * const controller = new AbortController(); * fetch('/api/data', { signal: controller.signal }); * * onScopeDispose(() => controller.abort()); * }); * * scope.stop(); // abort() is called * ``` */ export declare const onScopeDispose: (fn: CleanupFn) => void; //# sourceMappingURL=scope.d.ts.map