better isRx will determine if any parent to root is reactive
parent
543cad8bac
commit
4b76b80f07
128
src/rx-class.js
128
src/rx-class.js
|
@ -1,3 +1,4 @@
|
||||||
|
// import methods from './public-methods.js'
|
||||||
// native modules
|
// native modules
|
||||||
import { EventEmitter } from 'events'
|
import { EventEmitter } from 'events'
|
||||||
// reactive modules
|
// reactive modules
|
||||||
|
@ -5,7 +6,7 @@ import { BehaviorSubject, from } from 'rxjs'
|
||||||
import { distinctUntilChanged, skip } from 'rxjs/operators'
|
import { distinctUntilChanged, skip } from 'rxjs/operators'
|
||||||
// uci modules
|
// uci modules
|
||||||
import { check } from '@uci-utils/type'
|
import { check } from '@uci-utils/type'
|
||||||
import { get, set, del, getKeys, pathToString } from '@uci-utils/obj-nested-prop'
|
import { get, set, del, walkPath, getKeys, pathToString } from '@uci-utils/obj-nested-prop'
|
||||||
import { logger } from '@uci-utils/logger'
|
import { logger } from '@uci-utils/logger'
|
||||||
// supporting
|
// supporting
|
||||||
import equal from 'deep-equal'
|
import equal from 'deep-equal'
|
||||||
|
@ -17,7 +18,6 @@ const log = logger({ file: '/src/rx-class.js', package: '@uci-utils/rx-class', c
|
||||||
class RxClass extends EventEmitter {
|
class RxClass extends EventEmitter {
|
||||||
// private fields
|
// private fields
|
||||||
#rx
|
#rx
|
||||||
#rxM
|
|
||||||
|
|
||||||
constructor (opts = {}) {
|
constructor (opts = {}) {
|
||||||
super(opts)
|
super(opts)
|
||||||
|
@ -32,8 +32,9 @@ class RxClass extends EventEmitter {
|
||||||
hook: rxopts.hook, // function called when setting
|
hook: rxopts.hook, // function called when setting
|
||||||
namespace: rxopts.namespace || 'rx', // TODO namespace to added to all public rx methods
|
namespace: rxopts.namespace || 'rx', // TODO namespace to added to all public rx methods
|
||||||
operators: new Map(), // TODO added to all rx pipes, in order
|
operators: new Map(), // TODO added to all rx pipes, in order
|
||||||
skip: rxopts.skip == null ? 0 : rxopts.skip
|
skip: rxopts.skip == null ? 1 : rxopts.skip
|
||||||
}
|
}
|
||||||
|
this.isRx.bind(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
get (path) {
|
get (path) {
|
||||||
|
@ -51,25 +52,29 @@ class RxClass extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
set (path, value, opts = {}) {
|
set (path, value, opts = {}) {
|
||||||
// console.log(path,value,opts,!this.isRx(path))
|
console.log('set:', path, value, opts, !this.isRx(path))
|
||||||
if (!opts.noRx && !this.isRx(path)) {
|
if (!opts.noRx && !this.isRx(path)) { // travsere
|
||||||
opts = Object.assign(check.isPlainObject(value) ? { values: value, traverse: true } : { value: value }, opts)
|
opts = Object.assign(
|
||||||
// console.log('set opts', opts)
|
(check.isPlainObject(value) && opts.traverse !== false)
|
||||||
|
? { values: value, traverse: true }
|
||||||
|
: { value: value }
|
||||||
|
, opts)
|
||||||
|
console.log('adding rx from set', opts)
|
||||||
this.rxAdd(path, opts)
|
this.rxAdd(path, opts)
|
||||||
} else {
|
} else {
|
||||||
const curValue = this.#get(path)
|
const curValue = this.#get(path)
|
||||||
if (!equal(curValue, value) && value !== undefined) {
|
if (!equal(curValue, value) && value !== undefined) {
|
||||||
// console.log('in set', path,value)
|
console.log('setting already reactive value', path, value)
|
||||||
this.#set(path, value)
|
this.#set(path, value)
|
||||||
// console.log('value that was set',this.#get(path))
|
console.log('value that was set', this.#get(path))
|
||||||
}
|
}
|
||||||
return this.#get(path)
|
return this.#get(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRaw () {
|
getRaw () {
|
||||||
// return get(this, [this.#rx.namespace, ...arguments])
|
return get(this, [this.#rx.namespace, ...arguments])
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if property exists it moves value to #rx.props and creates getter and setter and behavior subject
|
// if property exists it moves value to #rx.props and creates getter and setter and behavior subject
|
||||||
rxAdd (path, opts = {}) {
|
rxAdd (path, opts = {}) {
|
||||||
|
@ -78,23 +83,24 @@ class RxClass extends EventEmitter {
|
||||||
const self = this
|
const self = this
|
||||||
// console.log('object to traverse', obj)
|
// console.log('object to traverse', obj)
|
||||||
traverse(obj).map(function () {
|
traverse(obj).map(function () {
|
||||||
|
// console.log('traversing', this)
|
||||||
if (this.isLeaf) {
|
if (this.isLeaf) {
|
||||||
const lpath = this.path
|
const lpath = this.path
|
||||||
lpath.unshift(path)
|
lpath.unshift(path)
|
||||||
// console.log(`#{!opts.values ? 'existing':'new'} leaf on path '#{lpath}' with value: #{this.node}`)
|
// console.log('#{!opts.values ? \'existing\':\'new\'} leaf on path \'#{lpath}\' with value: #{this.node}')
|
||||||
self.rxAdd(lpath, { value: this.node })
|
self.rxAdd(lpath, { value: this.node })
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
} // end traverse
|
} // end traverse
|
||||||
if (this.isRx(path) && !opts.force) return true
|
|
||||||
const value = this.#get(path) // current value
|
const value = this.#get(path) // current value
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
// console.log ('no current property or value for',path,'creating temporary null')
|
// console.log('no current property or value for', path, 'creating temporary null')
|
||||||
this.#set(path, null)
|
this.#set(path, null)
|
||||||
}
|
}
|
||||||
|
if (this.isRx(path) && !opts.force) return true
|
||||||
|
console.log(path, 'making reactive')
|
||||||
const { parent, name } = this.#rxGetObj(path, '__parent__')
|
const { parent, name } = this.#rxGetObj(path, '__parent__')
|
||||||
log.debug({
|
log.debug({
|
||||||
class: 'RxClass',
|
class: 'RxClass',
|
||||||
|
@ -149,6 +155,7 @@ class RxClass extends EventEmitter {
|
||||||
if (check.isFunction(rx.hook)) rx.hook.call(self, value) // property hook
|
if (check.isFunction(rx.hook)) rx.hook.call(self, value) // property hook
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// console.log('rxadd done', path, opts, this.#get(['#rx.props', path]))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +190,6 @@ class RxClass extends EventEmitter {
|
||||||
lpath.unshift(path)
|
lpath.unshift(path)
|
||||||
if (self.isRx(lpath)) self.rxRemove(lpath, { confirm: true })
|
if (self.isRx(lpath)) self.rxRemove(lpath, { confirm: true })
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
})
|
})
|
||||||
// all done removing the leaves so remove branch
|
// all done removing the leaves so remove branch
|
||||||
this.#del(['#rx.props', path], true)
|
this.#del(['#rx.props', path], true)
|
||||||
|
@ -244,29 +250,73 @@ class RxClass extends EventEmitter {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// // takes several formats for a path to an objects property and return only the . string
|
isGetSet (path) {
|
||||||
// formatObjPath (path) {
|
const keys = getKeys(path)
|
||||||
// if (path == null) return path
|
const prop = keys.pop()
|
||||||
// if (Array.isArray(path)) {
|
const parent = this.#get(keys)
|
||||||
// path = path.filter(Boolean).join('.') // Boolean filter strips empty strings or null/undefined
|
// console.log('isgetset', path, keys, prop, 'parent?', !!parent)
|
||||||
// }
|
if (parent && prop) {
|
||||||
// path = path.replace(/\/:,/g, '.') // replaces /:, with .
|
return !!(Object.getOwnPropertyDescriptor(parent, prop) || {}).get &&
|
||||||
// return path
|
!!(Object.getOwnPropertyDescriptor(parent, prop) || {}).set
|
||||||
// }
|
|
||||||
|
|
||||||
// checks for getter and the corresponding rx object
|
|
||||||
isRx (path) {
|
|
||||||
// console.log(path)
|
|
||||||
if (this.#get(path) === undefined) return false
|
|
||||||
const { parent, name, parentPath } = this.#rxGetObj(path, '__parent__')
|
|
||||||
// console.log(parent, name, parentPath)
|
|
||||||
const rxparent = this.#get(['#rx.props', parentPath]) || {}
|
|
||||||
const rx = rxparent[name]
|
|
||||||
// console.log(path, 'rxparent,rx', !!parent, !!name, !!rxparent, !!rx)
|
|
||||||
if (!rx) return false
|
|
||||||
// console.log(Object.getOwnPropertyDescriptor(parent, name).get)
|
|
||||||
return !!Object.getOwnPropertyDescriptor(parent, name).get
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// is already reactive, checks for setter/getter and the corresponding rx object
|
||||||
|
isRx (path) {
|
||||||
|
// console.log('in isRX', path)
|
||||||
|
const keys = getKeys(path)
|
||||||
|
const cnt = keys.length
|
||||||
|
for (let index = 0; index < cnt; index++) {
|
||||||
|
// console.log('testing rx', index, cnt, keys, !!this.#get(keys), !!this.isGetSet(keys), !!this.#get(['#rx.props', keys]))
|
||||||
|
if (this.#get(keys) === undefined) return false
|
||||||
|
if (this.isGetSet(keys) && this.#get(['#rx.props', keys])) return true
|
||||||
|
keys.pop()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
// // console.log('in rx every', lpath)
|
||||||
|
// // if (this.#get(['#rx.props', ...lpath]) === undefined) {
|
||||||
|
// // return false
|
||||||
|
// // }
|
||||||
|
// //
|
||||||
|
// console.log(parent, name, parentPath)
|
||||||
|
// const rxparent = this.#get(['#rx.props', parentPath]) || {}
|
||||||
|
// const rx = rxparent[name]
|
||||||
|
// console.log(path, 'rxparent,rx', !!parent, !!name, !!rxparent, !!rx)
|
||||||
|
// if (!rx) return true
|
||||||
|
// else {
|
||||||
|
// console.log(Object.getOwnPropertyDescriptor(parent, name).get)
|
||||||
|
// isRx = !!Object.getOwnPropertyDescriptor(parent, name).get
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// return isRx
|
||||||
|
}
|
||||||
|
|
||||||
|
// isRx(path) {
|
||||||
|
// // console.log(path)
|
||||||
|
// let isRx = false
|
||||||
|
// const lpath = []
|
||||||
|
// getKeys(path).every(key => {
|
||||||
|
// lpath.push(key)
|
||||||
|
// console.log('in rx every', lpath, this.#get(lpath))
|
||||||
|
// if (this.#get(lpath) === undefined) {
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// // const { parent, name, parentPath } = this.#rxGetObj(lpath, '__parent__')
|
||||||
|
// // console.log(parent, name, parentPath)
|
||||||
|
// const rxparent = this.#get(['#rx.props', parentPath]) || {}
|
||||||
|
// const rx = rxparent[name]
|
||||||
|
// console.log(path, 'rxparent,rx', !!parent, !!name, !!rxparent, !!rx)
|
||||||
|
// if (!rx) return true
|
||||||
|
// else {
|
||||||
|
// console.log(Object.getOwnPropertyDescriptor(parent, name).get)
|
||||||
|
// isRx = !!Object.getOwnPropertyDescriptor(parent, name).get
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// return isRx
|
||||||
|
// }
|
||||||
|
|
||||||
// PRIVATE METHODS
|
// PRIVATE METHODS
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue