import type { Agile } from '../agile'; import type { SubscriptionContainer } from './subscription'; import { CreateRuntimeJobConfigInterface, RuntimeJob } from './runtime.job'; import type { IngestConfigInterface } from './runtime'; export declare type ObserverKey = string | number; export declare class Observer { agileInstance: () => Agile; key?: ObserverKey; dependents: Set; subscribedTo: Set; value?: ValueType; previousValue?: ValueType; /** * An Observer manages the subscriptions to Subscription Containers (UI-Components) * and dependencies to other Observers (Agile Classes) * for an Agile Class such as the `State Class`. * * Agile Classes often use an Observer as an interface to the Runtime. * In doing so, they ingest their own Observer into the Runtime * when the Agile Class has changed in such a way * that these changes need to be applied to UI-Components * or dependent other Observers. * * After the Observer has been ingested into the Runtime * wrapped into a Runtime-Job, it is first added to the Jobs queue * to prevent race conditions. * When it is executed, the Observer's `perform()` method is called, * where the accordingly changes are applied to the Agile Class. * * Now that the Job was performed, it is added to the re-render queue, * where the subscribed Subscription Container (UI-Components) * of the Observer are updated (re-rendered). * * Note that the Observer itself is no standalone class * and should be adapted to the Agile Class needs it belongs to. * * @internal * @param agileInstance - Instance of Agile the Observer belongs to. * @param config - Configuration object */ constructor(agileInstance: Agile, config?: CreateObserverConfigInterface); /** * Passes the Observer into the runtime wrapped into a Runtime-Job * where it is executed accordingly. * * During the execution the runtime performs the Observer's `perform()` method, * updates its dependents and re-renders the UI-Components it is subscribed to. * * @public * @param config - Configuration object */ ingest(config?: ObserverIngestConfigInterface): void; /** * Method executed by the Runtime to perform the Runtime-Job, * previously ingested via the `ingest()` method. * * Note that this method should be overwritten * to correctly apply the changes to the Agile Class * the Observer belongs to. * * @public * @param job - Runtime-Job to be performed. */ perform(job: RuntimeJob): void; /** * Makes the specified Observer depend on the Observer. * * A dependent Observer is always ingested into the Runtime, * when the Observer it depends on has been ingested too. * * (Note: not mutating directly 'dependents' for better unit testing) * * @public * @param observer - Observer to depend on the Observer. */ addDependent(observer: Observer): void; /** * Makes the specified Observer no longer depend on the Observer. * * (Note: not mutating directly 'dependents' for better unit testing) * * @public * @param observer - Observer to no longer depend on the Observer. */ removeDependent(observer: Observer): void; } export interface CreateObserverConfigInterface { /** * Initial Observers to depend on the Observer. * @default [] */ dependents?: Array; /** * Initial Subscription Containers the Observer is subscribed to. * @default [] */ subs?: Array; /** * Key/Name identifier of the Observer. * @default undefined */ key?: ObserverKey; /** * Initial value of the Observer. * * The value of an Observer is given to the Integration's `updateMethod()` method * (Component Subscription Container) where it can be, * for example, merged in a local State Management property of the UI-Component * it is subscribed to. * * Also the selection of specific properties of an Agile Class value * is based on the Observer `value` and `previousValue`. * * @default undefined */ value?: ValueType; } export interface ObserverIngestConfigInterface extends CreateRuntimeJobConfigInterface, IngestConfigInterface { }