0.1.1
parent
3b1670e688
commit
3eef450669
|
@ -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,4 @@
|
|||
tests/
|
||||
test/
|
||||
*.test.js
|
||||
testing/
|
|
@ -0,0 +1,34 @@
|
|||
import { Observable } from 'rxjs'
|
||||
import Ready from '../src/ready'
|
||||
import { EventEmitter } from 'events'
|
||||
|
||||
let emitter = new EventEmitter()
|
||||
|
||||
let process = new Ready({emitter: emitter})
|
||||
|
||||
const tObs = new Observable(subscriber => {
|
||||
subscriber.next('on')
|
||||
subscriber.next('off')
|
||||
subscriber.next('enabled')
|
||||
setTimeout(() => {
|
||||
subscriber.next('F')
|
||||
subscriber.next('T')
|
||||
}, 2000)
|
||||
})
|
||||
|
||||
const tPromise = new Promise(function(resolve) {
|
||||
setTimeout(()=>resolve('yes'),3000)
|
||||
})
|
||||
|
||||
process.addObserver('e')
|
||||
process.addObserver('ec',(ev)=>ev.test)
|
||||
process.addObserver('pe',emitter)
|
||||
process.addObserver('obs',tObs)
|
||||
process.addObserver('pr',tPromise)
|
||||
|
||||
console.log(process.size)
|
||||
process.subscribe()
|
||||
|
||||
emitter.emit('ec',{test:true})
|
||||
emitter.emit('e','sure')
|
||||
emitter.emit('pe')
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"name": "@uci-utils/ready",
|
||||
"version": "0.1.1",
|
||||
"description": "A Class to Observe the reduced to boolean combined state of a map of observables",
|
||||
"main": "src/ready.js",
|
||||
"scripts": {
|
||||
"example": "node --r esm examples/example",
|
||||
"example:dev": "UCI_ENV=dev ./node_modules/.bin/nodemon -r esm examples/example",
|
||||
"test": "./node_modules/.bin/mocha -r esm --timeout 30000",
|
||||
"testd": "UCI_ENV=dev ./node_modules/.bin/nodemon --exec './node_modules/.bin/mocha -r esm --timeout 30000' || exit 0",
|
||||
"testdd": "UCI_LOG_LEVEL='trace' npm run testd",
|
||||
"testde": "UCI_LOG_LEVEL='warn' npm run testd",
|
||||
"testl": "UCI_ENV=pro UCI_LOG_PATH=./test/test.log 0 npm run test || exit 0"
|
||||
},
|
||||
"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": {
|
||||
"is-observable": "^2.0.0",
|
||||
"p-is-promise": "^3.0.0",
|
||||
"rxjs": "^6.5.4"
|
||||
},
|
||||
"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,105 @@
|
|||
import { from, fromEvent, combineLatest } from 'rxjs'
|
||||
import { map, startWith, tap } from 'rxjs/operators'
|
||||
import isObservable from 'is-observable'
|
||||
import isPromise from 'p-is-promise'
|
||||
|
||||
import { createBoolean } from '../../to-boolean'
|
||||
|
||||
const toBool = createBoolean({undefined:true})
|
||||
|
||||
class Ready extends Map {
|
||||
constructor(opts) {
|
||||
super(opts.observables)
|
||||
// TODO support setting registration in options
|
||||
this.emitter = typeof opts.emitter.on ==='function' ? opts.emitter : null
|
||||
this.condition = opts.condition || ( (ev) => toBool(ev) )
|
||||
this.subscriptions = new Map()
|
||||
this._state = {}
|
||||
this._updateObserversList()
|
||||
this.handler = opts.handler || ( ([r,s]) => {console.log('ready:',r,'states:',s,'\n---------------------------')})
|
||||
}
|
||||
|
||||
get state() {return this._state}
|
||||
|
||||
addObserver(name, obs, condition ) {
|
||||
if (!name) return false // name required
|
||||
if (!(obs || this.emitter)) return false // some observable requried
|
||||
if (typeof (obs ||{}).on ==='function') obs = fromEvent(obs,name) // it's an emitter
|
||||
if (isPromise(obs)) obs = from(obs) // it's a promise
|
||||
if (obs && !isObservable(obs) && typeof obs==='function' && arguments.length===2) {
|
||||
condition = obs
|
||||
obs = null
|
||||
}
|
||||
if (!obs && this.emitter) obs = fromEvent(this.emitter,name)
|
||||
if (!obs || !isObservable(obs)) return false
|
||||
this.set(name, obs
|
||||
.pipe(
|
||||
tap((ev) => console.log(name,'emitted/resolved=>',ev)),
|
||||
map(condition||this.condition),
|
||||
tap((b) => console.log('boolean:',b)),
|
||||
startWith(false),
|
||||
)
|
||||
)
|
||||
this._updateObserversList()
|
||||
return true
|
||||
}
|
||||
|
||||
removeObserver(names) {
|
||||
if (!names) this.clear
|
||||
else {
|
||||
if (!Array.isArray(names)) names = [names]
|
||||
names.forEach(name => {
|
||||
this.delete(name)
|
||||
})
|
||||
}
|
||||
this._updateObserversList()
|
||||
}
|
||||
|
||||
subscribe(name, handler) {
|
||||
if (typeof name ==='function') {
|
||||
handler=name
|
||||
name = null
|
||||
}
|
||||
this.subscriptions.set(name||'_primary', (name ? this.get(name):this._state).subscribe(handler||this.handler))
|
||||
}
|
||||
|
||||
unsubscribe(name) {
|
||||
this.subscriptions.get(name||'_primary').unsubscribe()
|
||||
}
|
||||
|
||||
_updateObserversList() {
|
||||
this._state = combineLatest(Array.from(this.values())).pipe(
|
||||
// tap((states)=>console.log('states',states)),
|
||||
map(states=> {
|
||||
return [states.reduce((res,state) => {return res && state},true), Array.from(this.keys()).map((name,index) => [name,states[index]])]
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// const toBoolean = (cond) =>
|
||||
// pipe(
|
||||
// map(cond),
|
||||
// startWith(false),
|
||||
// )
|
||||
|
||||
const rTrue=['t','true','y','yes','on','positive','up','enabled','affirmative','yea']
|
||||
const rFalse=['f','false','n','no','off','negative','down','disabled','nope']
|
||||
|
||||
function castBoolean (opts={}) {
|
||||
return (value => {
|
||||
if (value===undefined) return opts.undefined
|
||||
if (value===null) return opts.null
|
||||
if (!isNaN(Number(value))) return Number(value) <1 ? false :true
|
||||
if (typeof value==='string') {
|
||||
value = value.trim()
|
||||
value = value.toLowerCase()
|
||||
if ((opts.rTrue || rTrue).includes(value)) return true
|
||||
if ((opts.rFalse || rFalse).includes(value)) return false
|
||||
}
|
||||
return !!value
|
||||
})
|
||||
}
|
||||
|
||||
export default Ready
|
||||
export { Ready }
|
|
@ -0,0 +1,15 @@
|
|||
import { expect } from 'chai'
|
||||
import Ready from '../src/ready'
|
||||
|
||||
describe('', function () {
|
||||
|
||||
it('Should include custom types', function () {
|
||||
expect(u.isBuffer(Buffer.from('this is a test'))).to.equal(true)
|
||||
})
|
||||
|
||||
it('Should load typechecker', function () {
|
||||
expect(u.isPlainObject([1])).to.equal(false)
|
||||
|
||||
})
|
||||
|
||||
})
|
Loading…
Reference in New Issue