blow-collection
Version:
Simple in memory collection with Rx / Observable interface.
98 lines (84 loc) • 2.48 kB
text/typescript
;
import {Observable} from 'rxjs';
import {Query, QueryRaw, QueryWhere} from 'blow-query';
import {filter as buildFilter} from 'blow-filters';
import {isUndefined, isNumber} from 'util';
export function get(obj: any, key: string, defaultValue?: any): any {
return obj[key] || defaultValue;
}
export function set(obj: any, key: string, value: any): any {
obj[key] = value;
return obj;
}
export function has(obj: any, key: string): boolean {
return !isUndefined(get(obj, key));
}
export function dropReference(obj) {
return Object.assign({}, obj);
}
export function limit<T>(data$: Observable<T>, limit: number): Observable<T> {
if (isNumber(limit) && limit > 0) {
return data$.take(limit);
} else {
return data$;
}
}
export function skip<T>(data$: Observable<T>, skip: number): Observable<T> {
if (isNumber(skip)) {
return data$.skip(skip);
} else {
return data$;
}
}
export function sort<T>(data$: Observable<T>, sort: { [key: string]: number }): Observable<T> {
if (Object.keys(sort).length) {
return data$.toArray().mergeMap(rows => {
const fields = Object.keys(sort);
rows = rows.sort((rowA, rowB) => {
for (const field of fields) {
if (rowA[field] > rowB[field]) {
return 1 * sort[field];
} else if (rowA[field] < rowB[field]) {
return -1 * sort[field];
}
}
return 0;
});
return Observable.from(rows);
});
} else {
return data$;
}
}
export function prepareQuery(query: QueryRaw | Query): QueryRaw {
if (isUndefined(query)) {
query = {};
}
if (query instanceof Query) {
query = (<Query>query).toJSON();
}
return <QueryRaw>query;
}
export function where<T>(data$: Observable<T>, where: QueryWhere, invert?: boolean): Observable<T> {
invert = invert || false;
if (!Object.keys(where).length) {
return data$;
}
let filter;
if (invert) {
filter = row => !buildFilter(where)(row);
} else {
filter = buildFilter(where);
}
return data$.filter(filter);
}
export function filter<T>(data$: Observable<T>, query: QueryRaw | Query): Observable<T> {
const defaultQuery = { where: {}, sort: {}, limit: -1, skip: 0 };
query = prepareQuery(query);
const q: QueryRaw = Object.assign({}, defaultQuery, query);
data$ = where(data$, q.where);
data$ = sort(data$, q.sort);
data$ = skip(data$, q.skip);
data$ = limit(data$, q.limit);
return data$;
}