import { ThreadStream } from "../client/stream/index.cjs";
import { AcquiredProjection, ProjectionSpec, RootEventBus } from "./types.cjs";

//#region src/stream/channel-registry.d.ts
/**
 * Ref-counted, thread-aware projection registry.
 *
 * Owns the `spec.key → (store, runtime)` mapping for one
 * {@link StreamController}. Lifecycle:
 *
 *   - `acquire(spec)`  → +1 ref, returns `{ store, release }`. The
 *      first acquire opens the projection's runtime; subsequent
 *      acquires for the same key share both the store and the
 *      runtime.
 *   - `release()`      → -1 ref. When the last consumer releases,
 *      the entry is removed and its runtime disposed.
 *   - `bind(thread)`   → swap or detach the underlying thread; every
 *      live entry's runtime is recreated against the new thread,
 *      keeping the same store identity.
 *   - `dispose()`      → tear everything down (idempotent). Safe to
 *      call multiple times.
 *
 * The registry is intentionally not generic over a state shape —
 * different consumers can hold projections producing different
 * snapshot types, so the registry keys everything as `unknown` and
 * lets {@link acquire} reapply the caller's `T` at the boundary.
 */
declare class ChannelRegistry {
  #private;
  /**
   * Construct a registry bound to the controller's root event bus.
   *
   * The bus is forwarded to every projection's `open()` so root-scoped
   * projections can avoid opening a second server subscription when
   * their channel set is already covered by the root pump.
   *
   * @param rootBus - Read-only fan-out of the root subscription.
   */
  constructor(rootBus: RootEventBus);
  /**
   * Rebind every live entry to a new {@link ThreadStream} (or detach
   * when `thread == null`).
   *
   * Each live entry has its current runtime disposed (best-effort)
   * and its store reset to `entry.initial` so consumers see a clean
   * slate during the swap. When `thread != null`, a fresh runtime is
   * opened against the new thread.
   *
   * Critically the {@link StreamStore} *instance* is preserved across
   * the rebind: framework subscribers (e.g. React's
   * `useSyncExternalStore`) keep observing the same store reference,
   * so their subscriptions survive the swap.
   *
   * No-op when called with the currently bound thread.
   *
   * @param thread - The thread stream to bind, or `undefined` to detach.
   */
  bind(thread: ThreadStream | undefined): void;
  /** Currently bound thread (may be `undefined` pre-mount). */
  get thread(): ThreadStream | undefined;
  /**
   * Acquire a ref-counted projection.
   *
   * If no entry exists for `spec.key`, one is created (allocating a
   * {@link StreamStore} seeded with `spec.initial`) and — when a
   * thread is currently bound — its runtime is opened immediately.
   * If an entry already exists, its ref count is incremented and the
   * existing store is returned.
   *
   * The returned `release()` is idempotent: calling it more than once
   * is a no-op. When the ref count drops to zero, the entry is removed
   * and its runtime disposed (best-effort, never throws into callers).
   *
   * Safe to call from any framework lifecycle hook. Subsequent calls
   * for the same `spec.key` always return the same `store` reference
   * for the lifetime of the controller, so consumers can rely on store
   * identity.
   *
   * @typeParam T - Snapshot type produced by this projection.
   * @param spec - Projection contract; the registry keys off `spec.key`.
   * @returns A `{ store, release }` handle.
   */
  acquire<T>(spec: ProjectionSpec<T>): AcquiredProjection<T>;
  /**
   * Tear everything down.
   *
   * Detaches the bound thread (so no further `bind()` calls reopen
   * runtimes) and disposes every live runtime in parallel. Safe to
   * call multiple times — subsequent calls find an empty registry
   * and resolve immediately.
   */
  dispose(): Promise<void>;
  /**
   * Number of live entries. Diagnostic-only — callers should not
   * branch on this value at runtime; it exists for tests asserting
   * that consumers properly release their projections.
   */
  get size(): number;
}
//#endregion
export { ChannelRegistry };
//# sourceMappingURL=channel-registry.d.cts.map