import { Store } from 'data-store' import { BehaviorSubject, Subject, from } from 'rxjs' import { distinctUntilChanged, takeUntil } from 'rxjs/operators' import _get from 'get-value' import _set from 'set-value' import _del from 'unset-value' import equal from 'deep-equal' // import autobind from 'auto-bind' // ammend/react datastore class export default class StoreRx extends Store { constructor(opts){ // console.log('constructor', opts) super(opts) this.name = opts.name this._observers = {} this._deleted = {} this.emitter = opts.emitter this.event = opts.event || 'datastore' this.handler=opts.handler this.get = this.get.bind(this) this.set = this.set.bind(this) } // TODO manage all subscriptions getObs(path) { path = this.formatPath(path) return path ? _get(this._observers,path):this._observers } delObs(path) { // TODO support deleting all observers, would require traversing _observers path = this.formatPath(path) _get(this._deleted,path).next('deleted') _del(this._deleted,path) _del(this._observers,path) } setObs(path) { path = this.formatPath(path) const obs = this.getObs(path) if (obs) return obs _set(this._deleted,path,from(new Subject())) _set(this._observers,path,from(new BehaviorSubject(super.get(path))).pipe( distinctUntilChanged(), takeUntil(_get(this._deleted,path)) )) return this.getObs(path) } get(path,handler){ // console.log('get>>>>',path,handler) // console.log(this._observers) path = this.formatPath(path) if (typeof handler==='function') { let obs = this.getObs(path) if (!obs) obs = this.setObs(path) // console.log(obs) return obs.subscribe(handler) } return super.get(path) } // TODO trap delete and delete observer too set(path,value){ // TODO support path as object to merge per super.set // TODO if value not set del obs as well path = this.formatPath(path) const curValue = this.get(path) // console.log('set>>>>',path,curValue,value) if (!equal(curValue,value) || !value) { let obs = this.getObs(path) if (obs) obs.next(value) if (this.emit) this.emit(this.event,{path:path,key:path,value:value}) // console.log('pushing in datastore set',path,value) if (this.handler) this.handler({path:path,key:path,value:value}) return super.set(path,value) } return this } formatPath(path) { if (path==null) return path if (Array.isArray(path)) { path = path.filter(Boolean).join('.') } else path = path.replace(/\/:/g, '.') return path } } // end datastore class