93 lines
2.6 KiB
JavaScript
93 lines
2.6 KiB
JavaScript
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
|