import { DeferredPromise, type MaybePromise, type Simplify } from '@augment-vir/common'; import { type RemoveListenerCallback } from 'typed-event-target'; import { AnyObservable, type ObservableListener } from './any-observable.js'; import { type AsyncValue } from './async-value.js'; import { type EqualityCheck } from './equality-check.js'; import { type AllowNoUpdate, type ExcludeNoUpdate } from './no-update.js'; /** * Constructor input for {@link AsyncObservable}. * * @category Internal */ export type AsyncObservableInit = Partial<{ /** Starting value */ defaultValue: Promise> | ExcludeNoUpdate; /** * Callback to use to check equality between the current value and new values from * `.setValue()`. If the current value and the new value are equal, the new value will not be * set and no listeners will be called. Set this to undefined to disable equality checking, * which will then set values and fire listeners for every call of `.setValue()`. * * @default strict reference equality */ equalityCheck: EqualityCheck>> | undefined; }>; /** * The current state of an {@link AsyncValue}. * * @category Internal */ export declare enum AsyncValueState { /** The `.value` Promise has been rejected. */ Rejected = "rejected", /** The `.value` Promise has not settled yet. */ Waiting = "waiting", /** The `.value` Promise has been resolved into an awaited value. */ Resolved = "resolved" } /** * An observable that can handle promises and updates listeners for each stage in the promise * lifecycle. It also stores the last resolved value. * * @category Observable */ export declare class AsyncObservable extends AnyObservable { /** * The function used to check equality between different values. This can be manually set at any * time to change the function used. */ equalityCheck: AsyncObservableInit['equalityCheck']; protected waitingForValueDeferredPromise: DeferredPromise>; protected lastSetPromise: Promise> | undefined; /** Used to prevent setting different values from racing with each other. */ protected lastSetId: string; /** * The value which this observable currently contains. In this `AsyncObservable`, `value` may be * a promise, a resolved value, or an error. * * Do not set this directly. Use {@link AsyncObservable.setValue} instead. */ readonly value: AsyncValue; /** * The last resolved value. This only changes when `value` is set to a resolved value or when a * promise `value` resolves. * * Do not set this directly. Use {@link AsyncObservable.setValue} instead. */ readonly lastResolvedValue: ExcludeNoUpdate | undefined; constructor(init?: Readonly>); /** * Internally sets a new promise as the current value. This is called by * {@link AsyncObservable.setValue} if the given value is a promise. */ protected setPromise(newPromise: Promise>): boolean; /** * Internally updates the current value when a promise value has been resolved or a non-promise * value is given. */ protected resolveValue(value: AllowNoUpdate): boolean; /** * Internally updates the current value when a promise value has been rejected or an error value * is given. */ protected rejectValue(error: Error): void; /** * Set a new value to the observable. If a promise is used, `value` will be set to the promise * and `value` will be automatically overridden with the resolution or rejection result of the * promise once it's available. * * New resolved values will only be set and listeners will only be fired if it is not equal to * the current value (as determined by `equalityCheck`). * * @returns `true` if the new value was set, `false` otherwise. */ setValue(value: AllowNoUpdate>>): boolean; /** * Listen to changes in the observable's value. * * @returns A callback to remove the listener. */ listen( /** If true, the callback will immediately be fired with whatever the current value is. */ fireImmediately: boolean, /** The callback to fire when a new value is set on the observable. */ callback: ObservableListener): RemoveListenerCallback; /** * The current `.value` if it has resolved or `undefined` if it has not. * * Use this sparingly, as it prevents you from handling errors. Prefer `settledValue` instead. */ get resolvedValue(): Value | undefined; /** * The current `.value` if it has settled (into either a resolved value or an Error), or * `undefined` if it has not. */ get settledValue(): Error | Value | undefined; /** * The current `.value` as a promise. * * - If `.value` is currently an error, this returns a promise that immediately rejects with that * error. * - If `.value` is currently a resolved value, this returns a promise that immediately resolves * to that value. * - If `.value` is currently a promise, that promise is returned. */ get promiseValue(): Promise; /** The state of the current `.value`. */ get state(): AsyncValueState; }