@ebflat9/fp
Advanced tools
Comparing version 1.2.24 to 1.2.25
{ | ||
"name": "@ebflat9/fp", | ||
"version": "1.2.24", | ||
"version": "1.2.25", | ||
"description": "my fp utils", | ||
@@ -5,0 +5,0 @@ "source": "src/index.js", |
import { | ||
isObject, | ||
isFunction, | ||
@@ -7,2 +8,3 @@ isAsyncFunction, | ||
} from '../combinators.js' | ||
import { Observable } from '../rx.js' | ||
@@ -45,4 +47,2 @@ /** | ||
if (prop === 'clearCache') return () => (cache = Object.create(null)) | ||
if (isAsyncFunction(target[prop])) { | ||
@@ -102,2 +102,24 @@ return async function wrappedMethod() { | ||
if (isObject(target[prop])) { | ||
const cached = cache[prop] ?? {} | ||
let { observed, original } = cached | ||
// The target object must have changed, resub | ||
if (original !== target[prop]) { | ||
observed?.unsubscribe() | ||
observed = undefined | ||
original = target[prop] | ||
} | ||
if (!observed) { | ||
observed = Observable.makeObservable(target[prop]) | ||
observed.observe().subscribe(() => dispatchChanged(target, prop)) | ||
} | ||
return observed | ||
} | ||
if (prop === 'clearCache') return () => (cache = Object.create(null)) | ||
if (prop === 'isObserved') return () => subs.length > 0 | ||
return Reflect.get(...arguments) | ||
@@ -108,2 +130,9 @@ }, | ||
delete target[key] | ||
if (isObject(cache[key])) { | ||
cache[key].observed?.unsubscribe() | ||
delete cache[key].observed | ||
delete cache[key].original | ||
delete cache[key] | ||
} | ||
dispatchChanged(target, key) | ||
@@ -110,0 +139,0 @@ return true |
@@ -1401,3 +1401,78 @@ import { EventEmitter } from '../src/reactivize.js' | ||
}) | ||
it('should allow observing computed values', function (done) { | ||
const obj = { | ||
todos: [], | ||
get unfinishedTodosCount() { | ||
return this.todos.filter(todo => !todo.finished).length | ||
}, | ||
} | ||
const observed = Observable.makeObservable(obj) | ||
observed.observe().subscribe(value => { | ||
assert.deepEqual(value.todos, [{ name: 'Clean cat', finished: false }]) | ||
assert.equal(value.unfinishedTodosCount, 1) | ||
done() | ||
}) | ||
observed.todos.push({ name: 'Clean cat', finished: false }) | ||
}) | ||
it('should allow observing maps', function (done) { | ||
const obj = { | ||
people: new Map(), | ||
addPerson(name, details) { | ||
this.people.set(name, details) | ||
}, | ||
} | ||
const observed = Observable.makeObservable(obj) | ||
observed.observe().subscribe(value => { | ||
assert.deepEqual(value.people, new Map([['kevin', { age: 15 }]])) | ||
done() | ||
}) | ||
observed.people.set('kevin', { age: 15 }) | ||
}) | ||
it('should allow observing objects within arrays within objects', function (done) { | ||
const obj = { | ||
people: [{ name: 'tim', likes: ['cats'] }], | ||
} | ||
const observed = Observable.makeObservable(obj) | ||
observed.observe().subscribe(value => { | ||
assert.deepEqual(value, { people: [{ name: 'tim', likes: ['cats', 'dogs'] }] }) | ||
done() | ||
}) | ||
observed.people[0].likes.push('dogs') | ||
}) | ||
it('should allow reassigning properties and still observe them', function (done) { | ||
let called = 0 | ||
const obj = { | ||
list: ['a'], | ||
} | ||
const observed = Observable.makeObservable(obj) | ||
observed.observe().subscribe(value => { | ||
called++ | ||
if (called === 1) { | ||
assert.deepEqual(value, { list: ['hello'] }) | ||
} else if (called === 2) { | ||
assert.deepEqual(value, { list: ['hello', 'world'] }) | ||
} else if (called === 3) { | ||
assert.deepEqual(value, { list: ['cat'] }) | ||
} else { | ||
assert.deepEqual(value, { list: ['cat', 'dog'] }) | ||
done() | ||
} | ||
}) | ||
assert.equal(observed.isObserved(), true) | ||
observed.list = ['hello'] | ||
observed.list.push('world') | ||
observed.list = ['cat'] | ||
observed.list.push('dog') | ||
}) | ||
}) | ||
}) |
228482
7706