154 lines
4.1 KiB
JavaScript
154 lines
4.1 KiB
JavaScript
import NEDBP from 'nedb-promises'
|
|
import { BehaviorSubject as Subject, from } from 'rxjs'
|
|
import { distinctUntilChanged } from 'rxjs/operators'
|
|
import _getObj from 'get-value'
|
|
import _setObj from 'set-value'
|
|
import equal from 'deep-equal'
|
|
|
|
// ammend/react datastore class
|
|
export default class DataStore extends NEDBP {
|
|
constructor(opts){
|
|
super(opts)
|
|
this.name = opts.name
|
|
this._observers = {}
|
|
// console.log('collection observer', this.name)
|
|
// this.addObserver() // add observer for collection
|
|
// console.log('collection observer')
|
|
}
|
|
|
|
get indexes () {
|
|
return this.__original.indexes
|
|
}
|
|
|
|
get nedb() {
|
|
return this.__original
|
|
}
|
|
|
|
compact () {
|
|
this.__original.persistence.compactDatafile()
|
|
}
|
|
|
|
autoCompact(interval) {
|
|
this.__original.persistence.setAutocompactionInterval(interval)
|
|
}
|
|
|
|
addObserver (path,value) {
|
|
let [doc,prop] = (path||'').split('.')
|
|
let subj = new Subject(value||{})
|
|
let obs = from(subj).pipe(
|
|
distinctUntilChanged((p,c)=>{
|
|
// console.log(p,c)
|
|
// TODO allow deep prop looking and setting
|
|
if (prop) return equal(_getObj(p,prop),_getObj(c,prop))
|
|
return (equal(p,c))
|
|
})
|
|
)
|
|
this._set(path,obs)
|
|
return obs
|
|
}
|
|
|
|
_updateObserver (id,doc) {
|
|
// let obs = this.has(id)
|
|
// if (!obs) return false
|
|
// console.log('observer next',obs)
|
|
// obs.next(value)
|
|
// return true
|
|
}
|
|
|
|
_set(path,obs) {
|
|
let type
|
|
({type,path} = getObserverType.call(this,path))
|
|
_setObj(type,path,obs)
|
|
}
|
|
|
|
get (path) {
|
|
let obs = this.has(path)
|
|
if (!obs) obs = this.addObserver(path)
|
|
return obs
|
|
}
|
|
|
|
has (path) {
|
|
let type
|
|
({type,path} = getObserverType.call(this,path))
|
|
return _getObj(type,path)
|
|
}
|
|
|
|
subscribe (path,handler) {
|
|
if (typeof path === 'function') handler=path;path=null
|
|
let obs = this.get(path)
|
|
if (!obs) return false
|
|
if (typeof handler==='function') return obs.subscribe(handler)
|
|
else return obs
|
|
}
|
|
|
|
// async remove(arg){
|
|
async remove(obj,opts){
|
|
const id = obj._id
|
|
// console.log(this.name,'remove',id,opts)
|
|
this._updateObserver(id,null)
|
|
this._updateObserver()
|
|
await super.remove(...arguments)
|
|
}
|
|
|
|
async update(obj,doc){
|
|
const id = obj._id
|
|
// console.log(this.name, 'updating',doc._id||doc.id,doc.name||doc.hostname)
|
|
this._updateObserver(id,doc)
|
|
await super.update(...arguments)
|
|
}
|
|
|
|
async insert() {
|
|
// if (!Array.isArray(docs)) docs = [docs]
|
|
// console.log(this.name, 'inserting',docs.map(doc=>[doc._id||doc.id,doc.name||doc.hostname]))
|
|
let docs = await super.insert(...arguments)
|
|
// console.log(this.name,docs)
|
|
if (!Array.isArray(docs)) docs = [docs]
|
|
docs.forEach(doc =>{
|
|
// console.log('inserted', this.name, doc._id,doc.name)
|
|
// if !_getthis.addObserver(doc._id,doc)
|
|
})
|
|
}
|
|
|
|
async getID(id,prop) { // returns null for no results
|
|
let doc = {}
|
|
if (id) {
|
|
doc = await this.findOne({$or:[{_id:id},{hid:id}]})
|
|
if (!doc) {
|
|
if (arguments.length ===2) return null
|
|
// id might be missing so id is prop, use collection name as id
|
|
let doc = await this.findOne({_id:this.name})
|
|
return (doc ||{})[id]!=null ? doc[id] : doc
|
|
}
|
|
if (!prop) return doc
|
|
return (doc ||{})[prop]!=null? doc[prop] : null
|
|
}
|
|
// if no id passed look for id and prop same as store name
|
|
doc = await this.findOne({_id:this.name})
|
|
return (doc ||{})[this.name]!=null ? doc[this.name] : doc
|
|
}
|
|
|
|
async getAll() {
|
|
return await this.find({$not:{_id:'schema'}}) // return all but the schema
|
|
}
|
|
|
|
async patch (id, patch) {
|
|
let curDoc = await this.getID(id)
|
|
return await this.update({_id:id}, Object.assign(curDoc,patch))
|
|
}
|
|
|
|
} // end datastore class
|
|
|
|
|
|
function getObserverType(path) {
|
|
let doc;let prop; let type
|
|
if (typeof path!=='string') ({doc,prop}=path||{})
|
|
else [doc,prop] = (path||'').split(/[./:]/)
|
|
path = [doc,prop].filter(Boolean).join('.')
|
|
if (!prop)
|
|
if (!doc) type = this._observers
|
|
else type = this._observers.doc
|
|
else type = this._observers.prop
|
|
path = path==='' ? 'col' : (path || 'col')
|
|
return {path:path, type:type}
|
|
}
|