0.1.2 Removed the nedb promise datastore from controller and made it a stand alone class
Add rxjs reactivity for when documents and the properties change. a work in progressmaster
parent
f59c6fe4fe
commit
f1b6b14254
|
@ -0,0 +1,37 @@
|
|||
module.exports = {
|
||||
"ecmaFeatures": {
|
||||
"modules": true,
|
||||
"spread" : true,
|
||||
"restParams" : true
|
||||
},
|
||||
// "plugins": [
|
||||
// "unicorn"
|
||||
// ],
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2017,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
2
|
||||
],
|
||||
// "unicorn/no-array-instanceof": "error",
|
||||
"no-console": 0,
|
||||
"semi": ["error", "never"],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
/node_modules/
|
||||
/coverage/
|
|
@ -0,0 +1,5 @@
|
|||
tests/
|
||||
test/
|
||||
*.test.js
|
||||
testing/
|
||||
examples/
|
|
@ -0,0 +1,39 @@
|
|||
import DataStore from '../src/datastore'
|
||||
|
||||
// let circuits = await this.db.getAll('circuits')
|
||||
// console.log(circuits)
|
||||
// let obs = this.db.getStore('circuits').addObserver(undefined,'bogus')
|
||||
// let obs = this.db.getStore('circuits').addObserver('uy0cADaONfPv38th.prop1',{prop1:'test1'})
|
||||
// // console.log(this.db.getStore('circuits')._observers)
|
||||
// obs.subscribe(console.log)
|
||||
// obs.next({prop1:'test1'})
|
||||
// obs.next({prop1:'test1', prop2:{prop21:'test21',prop22:'test22'}})
|
||||
// obs.next({prop1:'test1', prop2:{prop21:'test21',prop22:'test22'}})
|
||||
// obs.next({prop1:'test1', prop2:{prop21:'test21',prop22:'test22x'}})
|
||||
// obs.next({prop1:'test2'})
|
||||
|
||||
|
||||
// let obs2 = this.db.getStore('circuits').addobs2erver('.prop1',{prop1:'test1'})
|
||||
// let obs2 = this.db.getStore('circuits').get()
|
||||
// console.log(this.db.getStore('circuits').subscribe(console.log))
|
||||
// // obs2.subscribe(console.log)
|
||||
// obs2.next({prop1:'test1'})
|
||||
// obs2.next({prop1:'test1', prop2:{prop21:'test21',prop22:'test22'}})
|
||||
// obs2.next({prop1:'test1', prop2:{prop21:'test21',prop22:'test22'}})
|
||||
// obs2.next({prop1:'test1', prop2:{prop21:'test21',prop22:'test22x'}})
|
||||
// obs2.next({prop1:'test2'})
|
||||
|
||||
|
||||
// let obs2 = this.db.getStore('circuits').addobs2erver('.prop1',{prop1:'test1'})
|
||||
// let obs2 = this.db.getStore('circuits').get()
|
||||
// console.log(this.db.getStore('circuits').subscribe(console.log))
|
||||
// // obs2.subscribe(console.log)
|
||||
// obs2.next([{prop1:'test1'},{prop1:'test1'}])
|
||||
// obs2.next([{prop1:'test1'},{prop1:'test1'}])
|
||||
// obs2.next([{prop1:'test1'},{prop1:'test1'},{prop1:'test1'}])
|
||||
// obs2.next([{prop1:'test1'},{prop1:'test1'},{prop1:'test1'}])
|
||||
// obs2.next([{prop1:'test1'},{prop1:'test1'},{prop1:'test2'}])
|
||||
// obs2.next([])
|
||||
// obs2.next()
|
||||
|
||||
// console.log(this.db.getStore('circuits')._observers)
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "@uci-utils/nedb-rx",
|
||||
"version": "0.1.2",
|
||||
"description": "A Class for promise Nedb with reactivity",
|
||||
"main": "src/datastore.js",
|
||||
"scripts": {
|
||||
"example": "node -r esm examples/example",
|
||||
"example:dev": "./node_modules/.bin/nodemon -r esm examples/example",
|
||||
"test": "./node_modules/.bin/mocha -r esm --timeout 30000"
|
||||
},
|
||||
"author": "David Kebler",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/uCOMmandIt/.git"
|
||||
},
|
||||
"keywords": [
|
||||
"node.js"
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/uCOMmandIt/uci-utils/issues"
|
||||
},
|
||||
"homepage": "https://github.com/uCOMmandIt/uci-utils#readme",
|
||||
"dependencies": {
|
||||
"deep-equal": "^2.0.1",
|
||||
"get-value": "^3.0.1",
|
||||
"is-plain-object": "^3.0.0",
|
||||
"nedb-promises": "^4.0.1",
|
||||
"rxjs": "^6.5.4",
|
||||
"set-value": "^3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "^4.2.0",
|
||||
"esm": "^3.2.25",
|
||||
"mocha": "^6.2.2",
|
||||
"nodemon": "^1.19.4"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
### uCOMmandIt Ready Class
|
||||
|
||||
Watches a list of events and/or promises that resolve to a boolean. When all a met it emits true otherwise at each event it emits false
|
|
@ -0,0 +1,153 @@
|
|||
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}
|
||||
}
|
Loading…
Reference in New Issue