@obsidize/rx-map
Version:
ES6 Map with rxjs extensions for change detection
73 lines (72 loc) • 2.81 kB
JavaScript
import { filter, map, scan } from 'rxjs/operators';
import { detectAccumulatedChanges, identity } from './utility';
import { isActionableChangeDetectionResultType } from '../events/change-detection-event';
/**
* Variant of filter() that uses a Set to increase lookup speed when checking emissions for a single property value.
* NOTE: this variant is top-heavy, and more expensive on smaller value lists; only use this when
* the 'values' collection can become large.
*/
export function spreadFilterBy(values, extractValue) {
const lookup = new Set(values);
return source => source.pipe(filter(v => lookup.has(extractValue(v))));
}
/**
* filter by map change event types (useful if you only want to watch ADD or UPDATE changes)
*/
export function ofType(...types) {
return source => source.pipe(spreadFilterBy(types, ev => ev.type));
}
/**
* filter by entity primary key
*/
export function forKey(key) {
return source => source.pipe(filter(ev => ev.key === key));
}
/**
* filter by a set of entity primary keys
*/
export function forKeyIn(keys) {
return source => source.pipe(spreadFilterBy(keys, ev => ev.key));
}
/**
* Narrows the scope of raw map change events into property-specific events.
*/
export function pluckValueChanges(selectValue) {
const selectSafe = (v) => v ? selectValue(v) : undefined;
return source => source.pipe(filter(ev => !!ev), map(ev => ({
entityId: ev.key,
currentValue: selectSafe(ev.value),
previousValue: selectSafe(ev.previousValue),
})));
}
/**
* map change events to their corresponding entity value
*/
export function pluckValue() {
return source => source.pipe(map(ev => ev.value), filter(identity));
}
/**
* map change events to their corresponding entity update differences (will be a partial entity object)
*/
export function pluckChanges() {
return source => source.pipe(map(ev => ev.changes), filter(identity));
}
/**
* capture emitted values and store them in the provided map reference by side-effect
*/
export function storeEntityIn(entityMap) {
return source => source.pipe(map(v => entityMap.setOne(v)));
}
/**
* capture emitted values and store them in the provided map reference by side-effect
*/
export function storeEntityArrayIn(entityMap) {
return source => source.pipe(map(v => entityMap.setMany(v)));
}
/**
* Emits change detection diffs between each emission and the one previous of it.
* NOTE: if the detection result type is NO_CHANGE, then the emission will be dropped.
*/
export function accumulateChanges() {
return source => source.pipe(scan((acc, current) => detectAccumulatedChanges(acc, current)), filter((next) => !!next && isActionableChangeDetectionResultType(next.type)));
}