import { Arr, Optional } from 'ts-data-forge'; import { type MutableSet } from 'ts-type-forge'; import { isRootObservable, type ChildObservable, type ObservableId, type RootObservable, } from '../types/index.mjs'; import { binarySearch, issueUpdateToken } from '../utils/index.mjs'; import { ObservableBaseClass } from './observable-base-class.mjs'; export class RootObservableClass extends ObservableBaseClass implements RootObservable { #mut_propagationOrder: readonly ChildObservable[]; protected readonly _descendantsIdSet: MutableSet; constructor({ initialValue, }: Readonly<{ initialValue: Optional; }>) { super({ kind: 'root', depth: 0, initialValue, }); this.#mut_propagationOrder = []; this._descendantsIdSet = new Set(); } addDescendant(child: ChildObservable): void { if (this._descendantsIdSet.has(child.id)) return; this._descendantsIdSet.add(child.id); const insertPos = binarySearch( this.#mut_propagationOrder.map((a) => a.depth), child.depth, ); this.#mut_propagationOrder = Arr.toInserted( this.#mut_propagationOrder, insertPos, child, ); } startUpdate(nextValue: A): void { const updateToken = issueUpdateToken(); this.setNext(nextValue, updateToken); for (const p of this.#mut_propagationOrder) { p.tryUpdate(updateToken); } } } if (import.meta.vitest !== undefined) { test('isRootObservable', () => { assert.isTrue( isRootObservable( new RootObservableClass({ initialValue: Optional.some(0), }), ), ); }); }