@difizen/mana-observable
Version:
78 lines (72 loc) • 2.01 kB
text/typescript
import { Disposable, Event } from '@difizen/mana-common';
import type { Notify } from './core';
import { Notifier } from './notifier';
import { observable } from './observable';
import { getOrigin, Observability } from './utils';
function tryObservable<T>(target: T) {
const data = getOrigin(target);
if (!Observability.canBeObservable(data)) {
return data;
}
if (!Observability.marked(data)) {
return observable(data);
}
return data;
}
function watchAll<T>(target: T, callback: Notify): Disposable {
const data = getOrigin(target);
if (!Observability.canBeObservable(data)) {
return Disposable.NONE;
}
tryObservable(data);
const event = Notifier.toEvent(data);
if (event === Event.None) {
console.warn('Cannot add watcher for unobservable target', target);
return Disposable.NONE;
}
const props: string[] = Object.keys(data);
if (props) {
props.forEach((prop) => Notifier.find(target, prop));
}
return event(callback);
}
function watchProp<T>(
target: T,
prop: Extract<keyof T, string>,
callback: Notify,
): Disposable {
const origin = getOrigin(target);
tryObservable(origin);
const event = Notifier.toEvent(origin, prop);
if (event === Event.None) {
console.warn(
`Cannot add watcher for unobservable property ${prop.toString()}`,
target,
);
return Disposable.NONE;
}
return event(callback);
}
export function watch<T>(target: T, callback: Notify): Disposable;
export function watch<T>(
target: T,
prop: Extract<keyof T, string>,
callback: Notify,
): Disposable;
export function watch<T>(
target: T,
prop: Extract<keyof T, string> | Notify,
callback?: Notify,
): Disposable {
let cb: Notify;
if (typeof prop === 'function') {
cb = prop;
return watchAll(target, cb);
}
if (typeof prop === 'string' && callback) {
cb = callback;
return watchProp(target, prop, cb);
}
console.warn(`Invalid arguments for watch ${prop.toString()}`, target);
return Disposable.NONE;
}