interface Reactive<T>{
    readonly value: T;
    update: () => Promise<void>;
    wireTo(...r: Reactive<unknown>[]): void;
    unwireTo(r: Reactive<unknown>): void;
}

export async function createReactive<T>(fn: () => Promise<T>): Promise<Reactive<T>> {
    let v = await fn();
    let listeners: Reactive<unknown>[] = [];

    return {
        get value() : T {
            return v;
        },
        async update(){
            const ret = await fn();
            v = ret;
            await Promise.all(listeners.map(o => o.update()));
        },
        wireTo(...r: Reactive<unknown>[]) {
            listeners.push(...r);
        },
        unwireTo(r: Reactive<unknown>) {
            listeners = listeners.filter(o => o !== r);
        }
    };
}