import { DisposableStore } from "./commonFacade/deps.js"; /** * Represents an observable value. * * @template T The type of the values the observable can hold. */ export interface IObservable extends IObservableWithChange { } /** * Represents an observable value. * * @template T The type of the values the observable can hold. * @template TChange The type used to describe value changes * (usually `void` and only used in advanced scenarios). * While observers can miss temporary values of an observable, * they will receive all change values (as long as they are subscribed)! */ export interface IObservableWithChange { /** * Returns the current value. * * Calls {@link IObserver.handleChange} if the observable notices that the value changed. * Must not be called from {@link IObserver.handleChange}! */ get(): T; /** * Forces the observable to check for changes and report them. * * Has the same effect as calling {@link IObservable.get}, but does not force the observable * to actually construct the value, e.g. if change deltas are used. * Calls {@link IObserver.handleChange} if the observable notices that the value changed. * Must not be called from {@link IObserver.handleChange}! */ reportChanges(): void; /** * Adds the observer to the set of subscribed observers. * This method is idempotent. */ addObserver(observer: IObserver): void; /** * Removes the observer from the set of subscribed observers. * This method is idempotent. */ removeObserver(observer: IObserver): void; /** * Reads the current value and subscribes the reader to this observable. * * Calls {@link IReader.readObservable} if a reader is given, otherwise {@link IObservable.get} * (see {@link ConvenientObservable.read} for the implementation). */ read(reader: IReader | undefined): T; /** * Makes sure this value is computed eagerly. */ recomputeInitiallyAndOnChange(store: DisposableStore, handleValue?: (value: T) => void): IObservable; /** * Makes sure this value is cached. */ keepObserved(store: DisposableStore): IObservable; /** * Creates a derived observable that depends on this observable. * Use the reader to read other observables * (see {@link ConvenientObservable.map} for the implementation). */ map(fn: (value: T, reader: IReader) => TNew): IObservable; map(owner: object, fn: (value: T, reader: IReader) => TNew): IObservable; flatten(this: IObservable>): IObservable; /** * ONLY FOR DEBUGGING! * Logs computations of this derived. */ log(): IObservableWithChange; /** * A human-readable name for debugging purposes. */ readonly debugName: string; /** * This property captures the type of the change object. Do not use it at runtime! */ readonly TChange: TChange; } /** * Represents an observer that can be subscribed to an observable. * * If an observer is subscribed to an observable and that observable didn't signal * a change through one of the observer methods, the observer can assume that the * observable didn't change. * If an observable reported a possible change, {@link IObservable.reportChanges} forces * the observable to report an actual change if there was one. */ export interface IObserver { /** * Signals that the given observable might have changed and a transaction potentially modifying that observable started. * Before the given observable can call this method again, is must call {@link IObserver.endUpdate}. * * Implementations must not get/read the value of other observables, as they might not have received this event yet! * The method {@link IObservable.reportChanges} can be used to force the observable to report the changes. */ beginUpdate(observable: IObservable): void; /** * Signals that the transaction that potentially modified the given observable ended. * This is a good place to react to (potential) changes. */ endUpdate(observable: IObservable): void; /** * Signals that the given observable might have changed. * The method {@link IObservable.reportChanges} can be used to force the observable to report the changes. * * Implementations must not get/read the value of other observables, as they might not have received this event yet! * The change should be processed lazily or in {@link IObserver.endUpdate}. */ handlePossibleChange(observable: IObservable): void; /** * Signals that the given {@link observable} changed. * * Implementations must not get/read the value of other observables, as they might not have received this event yet! * The change should be processed lazily or in {@link IObserver.endUpdate}. * * @param change Indicates how or why the value changed. */ handleChange(observable: IObservableWithChange, change: TChange): void; } /** * A reader allows code to track what it depends on, so the caller knows when the computed value or produced side-effect is no longer valid. * Use `derived(reader => ...)` to turn code that needs a reader into an observable value. */ export interface IReader { /** * Reads the value of an observable and subscribes to it. */ readObservable(observable: IObservableWithChange): T; } export interface ISettable { /** * Sets the value of the observable. * Use a transaction to batch multiple changes (with a transaction, observers only react at the end of the transaction). * * @param transaction When given, value changes are handled on demand or when the transaction ends. * @param change Describes how or why the value changed. */ set(value: T, transaction: ITransaction | undefined, change: TChange): void; } export interface ITransaction { /** * Calls {@link Observer.beginUpdate} immediately * and {@link Observer.endUpdate} when the transaction ends. */ updateObserver(observer: IObserver, observable: IObservableWithChange): void; } /** * This function is used to indicate that the caller recovered from an error that indicates a bug. */ export declare function handleBugIndicatingErrorRecovery(message: string): void; /** * A settable observable. */ export interface ISettableObservable extends IObservableWithChange, ISettable { } export interface IReaderWithStore extends IReader { /** * Items in this store get disposed just before the observable recomputes/reruns or when it becomes unobserved. */ get store(): DisposableStore; /** * Items in this store get disposed just after the observable recomputes/reruns or when it becomes unobserved. * This is important if the current run needs the undisposed result from the last run. * * Warning: Items in this store might still get disposed before dependents (that read the now disposed value in the past) are recomputed with the new (undisposed) value! * A clean solution for this is ref counting. */ get delayedStore(): DisposableStore; }