import type { Clock } from "../clock.ts"; import type { ProtectLogging } from "../logging.ts"; import type { ProtectNvrBootstrap } from "../types/index.ts"; import type { ProtectState } from "../protocol/reducer.ts"; import type { TypedEvent } from "../protocol/events.ts"; /** * Construction options for {@link StateStore}. * * - `refresh` is the only required option: the seam the failsafe calls to fetch a fresh bootstrap. The composition root wires it to a transport request; tests wire a * fake. Injecting a function rather than a `Transport` is what keeps the store at the data layer (it never imports the transport) and deterministically testable. * - `refreshIntervalMs` defaults to {@link PROTECT_BOOTSTRAP_REFRESH_INTERVAL}; pass `false` or a non-positive interval to disable the failsafe entirely (the consumer * then relies solely on the realtime event stream). * * @category State */ export interface StateStoreOptions { clock?: Clock; initialState?: ProtectState; log?: ProtectLogging; refresh: () => Promise; refreshIntervalMs?: number | false; } /** * The canonical state holder. See the module doc for the model. Constructed by `ProtectClient.connect()`; consumers read it as `client.state`. * * @category State */ export declare class StateStore implements AsyncDisposable { #private; constructor(options: StateStoreOptions); /** * The current state. Synchronous and reference-stable between dispatches - safe to read on a hot path and to compare with `Object.is`. * * @returns The current {@link ProtectState}. */ snapshot(): ProtectState; /** * Observe a selector over the state. The returned async iterable yields the selector's output once at every point the value *changes* by reference, and never on a * dispatch that left the value unchanged. Pair it with {@link StateStore.snapshot} for the current value: snapshot for "what is it now", observe for "tell me when * it changes". * * Termination: pass `opts.signal` to end the iteration (the iterator returns cleanly on abort), or simply `break` out of the `for await` - either path unregisters * the observer. An already-aborted signal yields nothing. * * @typeParam T - The selector's output type. * * @param selector - A pure function from state to the value of interest. Use the memoized selectors in `state/selectors.ts` so unchanged collections compare equal. * @param opts - Optional abort signal that terminates the iteration. * * @returns An async iterable of the selector's value at each change. */ observe(selector: (state: ProtectState) => T, opts?: { signal?: AbortSignal; }): AsyncGenerator; /** * Advance the state by one event. The single mutation chokepoint: it folds the event through the pure reducer and, only when the resulting state is a *different* * reference, commits it and notifies every active observer. A no-op event (one the reducer returns unchanged) notifies nobody. * * Package-internal: the realtime event stream, the refresh failsafe, and the `connect()` factory's initial bootstrap call it. It is not a consumer-facing surface. * * @param event - The typed event to apply. * * @internal */ dispatch(event: TypedEvent): void; /** * Stop the refresh failsafe and terminate every open observer. Idempotent. */ [Symbol.asyncDispose](): Promise; } //# sourceMappingURL=store.d.ts.map