UNPKG

blow-collection

Version:

Simple in memory collection with Rx / Observable interface.

125 lines (103 loc) 3.24 kB
'use strict'; import {Observable} from 'rxjs'; import {Query, QueryRaw, QueryWhere} from 'blow-query'; import * as uuid from 'node-uuid'; import * as _ from './helpers'; import {CollectionOptions} from './interfaces'; export class Collection<T> { protected _data: T[]; protected _idKey: string; protected _idGenerator: () => string | number; constructor(options?: CollectionOptions) { options = options || {}; this._idKey = options.idKey || '_id'; this._idGenerator = options.idGenerator || (() => uuid.v4()); this._data = []; } get size(): number { return this._data.length; } protected get _data$(): Observable<T> { return Observable.from(this._data); } protected _getId(data: any): any { return _.get(data, this._idKey); } protected _setId(data: any, id?: any): any { return _.set(data, this._idKey, id || this._idGenerator()); } protected _hasId(data: any): boolean { return _.has(data, this._idKey); } create(data: any): Observable<T> { data = _.dropReference(data); if (!this._hasId(data)) { data = this._setId(data); } this._data.push(data); return Observable.of(_.dropReference(data)); } update(where: QueryWhere, data: any): Observable<number> { return _.where(this._data$, where) .map(row => Object.assign(row, data)) .count(); } updateOrCreate(data: any): Observable<T> { if (this._hasId(data)) { return this.findById(this._getId(data)) .defaultIfEmpty() .mergeMap(current => { if (!current) { return this.create(data); } else { Object.assign(current, data); return Observable.of(_.dropReference(current)); } }); } else { return this.create(data); } } count(where?: QueryWhere): Observable<number> { where = where || {}; return _.where(this._data$, where).count(); } destroy(where?: QueryWhere): Observable<number> { where = where || {}; return _.where(this._data$, where, true) .toArray() .map(rows => { const count = this._data.length - rows.length; this._data = rows; return count; }); } destroyById(id: any): Observable<boolean> { const where = this._setId({}, id); return this.destroy(where).map(num => !!num); } find(query?: QueryRaw | Query): Observable<T> { query = _.prepareQuery(query); return _.filter(this._data$, query).map(row => Object.assign({}, row)); } findOne(query?: QueryRaw | Query): Observable<T> { query = _.prepareQuery(query); return this.find(Object.assign(query, { limit: 1 })); } findById(id: any): Observable<T> { const where = this._setId({}, id); return _.filter(this._data$, { where }).map(row => Object.assign({}, row)); } findOrCreate(where: QueryWhere, data: any): Observable<T> { return this.findOne({ where }).defaultIfEmpty().mergeMap(current => { if (!current) { return this.create(data); } else { return Observable.of(_.dropReference(current)); } }); } exists(id: any): Observable<boolean> { return this.findById(id).map(row => !!row).defaultIfEmpty(false); } }