UNPKG

@obsidize/rx-map

Version:

ES6 Map with rxjs extensions for change detection

89 lines (88 loc) 2.88 kB
import { Subject } from 'rxjs'; import { filter, map, share } from 'rxjs/operators'; import { MapStateChangeEventType } from '../events/map-state-change-event'; import { isActionableChangeDetectionResultType } from '../events/change-detection-event'; import { extractChanges } from '../common/utility'; import { ImmutableMap } from './immutable-map'; /** * Extension of the standard ES6 Map with rxjs change event observables tacked on. */ export class RxMap { constructor(source) { this.source = source; this.mStateChangeSubject = new Subject(); this.allChanges = this.mStateChangeSubject.asObservable().pipe(share()); this.changes = this.allChanges.pipe(map(ev => extractChanges(ev)), filter(ev => isActionableChangeDetectionResultType(ev.changeType)), share()); } /** * Generate an RxMap instance with a standard (mutable) Map store. */ static mutable() { return new RxMap(new Map()); } /** * Generate an RxMap instance with an immutable backend store. */ static immutable() { return new RxMap(ImmutableMap.standard()); } emit(type, key, value, previousValue, context = { source: 'unknown' }) { this.mStateChangeSubject.next({ type, key, value, previousValue, context }); } emitSet(key, value, previousValue, context) { this.emit(MapStateChangeEventType.SET, key, value, previousValue, context); } emitDelete(key, value, context) { this.emit(MapStateChangeEventType.DELETE, key, value, undefined, context); } get size() { return this.source.size; } get [Symbol.toStringTag]() { return 'RxMap'; } [Symbol.iterator]() { return this.entries(); } get(key) { return this.source.get(key); } has(key) { return this.source.has(key); } entries() { return this.source.entries(); } keys() { return this.source.keys(); } values() { return this.source.values(); } forEach(callbackfn) { this.source.forEach(callbackfn); } destroy() { const s = this.mStateChangeSubject; if (s.closed && s.isStopped) return; s.error('destroyed'); s.unsubscribe(); } clear() { const keys = Array.from(this.keys()); keys.forEach(key => this.delete(key)); } delete(key, context) { const value = this.get(key); const didDelete = this.source.delete(key); this.emitDelete(key, value, context); return didDelete; } set(key, value, context) { const previousValue = this.get(key); this.source.set(key, value); this.emitSet(key, value, previousValue, context); return this; } }