UNPKG

rxdeep

Version:
108 lines 4.44 kB
import { Observable, Subject } from 'rxjs'; import { map, filter, multicast, refCount, startWith, tap, distinctUntilChanged } from 'rxjs/operators'; import { State } from './state'; import { isLeaf } from './types/changes'; import { Watcher } from './util/watcher'; import { trace } from './trace'; export class KeyedState extends Observable { constructor(state, keyfunc) { super((observer) => { return this._changes.pipe(map(([change, _]) => change.value || []), startWith(this.value)).subscribe(observer); }); this.state = state; this.keyfunc = keyfunc; this._value = []; this._watcher = new Watcher(state.value, keyfunc); this._value = state.value || []; this._changesub = new Subject(); this._changes = this.state.downstream.pipe(map(change => [change, this._watcher.changes(change.value)]), map(([change, listChanges]) => { if (listChanges.moves.length > 0 && !isLeaf(change.trace)) { const mapping = listChanges.moves.reduce((total, move) => { total[move.oldIndex] = move.newIndex; return total; }, {}); const _tr = { subs: Object.assign({}, change.trace.subs) }; Object.entries(mapping).forEach(([src, dest]) => { const subtrace = trace(this._value[src], change.value[dest]); if (subtrace) { _tr.subs[dest] = subtrace; } else { delete _tr.subs[dest]; } }); return [{ value: change.value, trace: _tr }, listChanges]; } return [change, listChanges]; }), tap(([change]) => { this._value = change.value || []; }), multicast(() => this._changesub), refCount()); } next(t) { this.state.upstream.next({ value: t, trace: { from: this.value, to: t } }); } error(err) { this.state.upstream.error(err); } complete() { this._changesub.complete(); } get value() { return this._value; } set value(t) { this.next(t); } key(key) { var _a; const sub = new State((_a = this._watcher.keymap[key]) === null || _a === void 0 ? void 0 : _a.item, this.keyDownstream(key, () => sub.value), this.keyUpstream(key)); return sub; } keyDownstream(key, current) { return this._changes.pipe(map(([change, _]) => ({ trace: change.trace, entry: this._watcher.keymap[key], })), filter(change => { /* istanbul ignore next */ if (isLeaf(change.trace)) { return current() !== change.entry.item; } else { return (!change.entry && !!current()) || (change.entry && change.entry.index in change.trace.subs); } }), map(change => { var _a; return ({ value: (_a = change.entry) === null || _a === void 0 ? void 0 : _a.item, trace: isLeaf(change.trace) || !change.entry ? undefined : change.trace.subs[change.entry.index] }); })); } keyUpstream(key) { return { next: change => { const entry = this._watcher.keymap[key]; this._value[entry.index] = change.value; this.state.upstream.next({ value: this._value, trace: { subs: { [entry.index]: change.trace } } }); }, error: err => this.state.upstream.error(err), complete: () => { }, }; } index(key) { var _a; return this._changes.pipe(map(() => { var _a; return (_a = this._watcher.keymap[key]) === null || _a === void 0 ? void 0 : _a.index; }), startWith((_a = this._watcher.keymap[key]) === null || _a === void 0 ? void 0 : _a.index), distinctUntilChanged()); } changes() { return this._changes.pipe(map(([_, listChanges]) => listChanges)); } } export function keyed(state, keyfunc) { return new KeyedState(state, keyfunc); } //# sourceMappingURL=keyed.js.map