@platform/state
Version:
A small, simple, strongly typed, [rx/observable] state-machine.
56 lines (55 loc) • 1.7 kB
JavaScript
import { Subject } from 'rxjs';
import { filter, map, takeUntil } from 'rxjs/operators';
export function syncFrom(args) {
const { target } = args;
const parent = (args.parent || '').trim();
if (!parent) {
const err = `Cannot sync: parent node not specified.`;
throw new Error(err);
}
if (!target.query.exists(parent)) {
const err = `Cannot sync: the parent node '${parent}' does not exist in tree '${target.id}'.`;
throw new Error(err);
}
const dispose$ = new Subject();
const dispose = () => {
dispose$.next();
dispose$.complete();
};
target.dispose$.subscribe(() => dispose());
if (args.until$) {
args.until$.subscribe(() => dispose());
}
const source$ = args.source$.pipe(takeUntil(dispose$), filter((e) => e.type === 'TreeState/changed'), map((e) => e.payload));
const change = (to) => {
target.change((draft, ctx) => {
const node = ctx.findById(parent);
if (node) {
ctx.children(node, (children) => {
const index = children.findIndex((child) => child.id === to.id);
if (index === -1) {
children.push(to);
}
else {
children[index] = to;
}
});
}
});
};
if (args.initial) {
change(args.initial);
}
source$.subscribe((e) => {
change(e.to);
});
const syncer = {
parent,
get isDisposed() {
return dispose$.isStopped;
},
dispose$,
dispose,
};
return syncer;
}