Research
Security News
Threat Actor Exposes Playbook for Exploiting npm to Build Blockchain-Powered Botnets
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
@nx-js/observer-util
Advanced tools
An NX utility, responsible for powerful transparent reactivity with ES6 Proxies.
Transparent reactivity without special syntax and with a 100% language observability coverage. It uses ES6 Proxies internally to work seamlessly with a minimal interface.
React Easy State is a React state management solution - based on this library. This library is part of the NX framework.
$ npm install @nx-js/observer-util
This library has two main functions. observable
turns the passed object into an observable object and observe
turns the passed function into a reaction. A reaction is automatically executed whenever an observable property - which is used inside the reaction - changes value. Reactions are executed in an async batch, after a small delay.
import { observable, observe } from '@nx-js/observer-util'
const person = observable({ firstName: 'Bob', lastName: 'Smith' })
// this reaction automatically re-runs whenever person.firstName or person.lastName changes
observe(() => console.log(`${person.firstName} ${person.lastName}`))
// this logs 'John Smith' to the console
setTimeout(() => person.firstName = 'John')
Any JavaScript code is correctly observed in reactions - including expando properties, loops, getters/setters, inheritance and ES6 collections. Check out the examples section for more.
No special syntax or setup is required, you will likely use the observable
and observe
functions only.
Observable objects are not modified at all. The underlying raw object can be easily retrieved and used when you don't want to trigger reactions.
Triggered reactions run asynchronously, but always before the next repaint in browsers. Your reactions reach a stable and fresh state before repaints.
Duplicates and loops are automatically removed from triggered reactions. This ensures that your code won't run twice without a reason.
Creates and returns an observable object.
import { observable } from '@nx-js/observer-util'
const person = observable({ name: 'Ann' })
Returns true if the passed object is an observable, otherwise returns false.
import { observable, isObservable } from '@nx-js/observer-util'
const person = observable()
const isPersonObservable = isObservable(person)
Turns the passed function into a reaction, then executes and returns it. A reaction automatically reruns when a property of an observable - which is used by the reaction - changes.
import { observable, observe } from '@nx-js/observer-util'
const counter = observable({ num: 0 })
// this logs the value of counter.num whenever it changes
const logger = observe(() => console.log(counter.num))
Unobserves the passed reaction. Unobserved reactions won't be automatically run anymore.
import { observable,observe, unobserve } from '@nx-js/observer-util'
const counter = observable({ num: 0 })
const logger = observe(() => console.log(counter.num))
// after this counter.num won't be automatically logged on changes
unobserve(logger)
Removes the the reaction function from the queue of triggered reactions. This means that the reaction won't run in the next batch, unless another observable mutation triggers it.
import { observe, unqueue } from '@nx-js/observer-util'
const counter = observable({ num: 0 })
const logger = observe(() => console.log(counter.num))
// counter.num is changed and it queues the logger reaction
counter.num++
// this removes the logger reaction from the queue, so it won't run
unqueue(logger)
Immediately runs the passed reaction. Never run a reaction directly, use this method instead. Running the reaction with a direct call may cause it to not discover observable property access in some of its parts.
import { observable, observe, exec } from '@nx-js/observer-util'
const person = observable({ name: 'Bob' })
const logger = observe(() => console.log(person.name))
exec(logger)
Runs the passed callback after the queued reactions run. It also returns a Promise, which resolves after the reactions. This comes handy for testing.
import { observable, observe, nextTick } from '@nx-js/observer-util'
let dummy
const counter = observable({num: 0})
observe(() => dummy = counter.num)
counter.num = 7
await nextTick()
// the reactions ran during the tick, the 'dummy' is already updated to be 7
expect(dummy).to.equal(7)
Every observable object has a $raw
virtual property. It can be used to access the underlying non-observable object. Modifying and accessing the raw object doesn't trigger reactions.
$raw
for property access in reactionsimport { observable, observe } from '@nx-js/observer-util'
const person = observable()
const logger = observe(() => console.log(person.name))
// this logs 'Bob'
setTimeout(() => person.name = 'Bob')
// this won't log anything
setTimeout(() => person.$raw.name = 'John')
$raw
at observable mutationsimport { observable, observe } from '@nx-js/observer-util'
const person = observable({ age: 20 })
observe(() => console.log(`${person.name}: ${person.$raw.age}`))
// this logs 'Bob: 20'
setTimeout(() => person.name = 'Bob')
// this won't log anything
setTimeout(() => person.age = 33)
import { observable, observe } from '@nx-js/observer-util'
const profile = observer.observable()
observe(() => console.log(profile.name))
// logs 'Bob'
setTimeout(() => profile.name = 'Bob')
import { observable, observe } from '@nx-js/observer-util'
const person = observable({
gender: 'male',
name: 'Potato'
})
observe(() => {
if (person.gender === 'male') {
console.log(`Mr. ${person.name}`)
} else {
console.log(`Ms. ${person.name}`)
}
})
// logs 'Ms. Potato'
setTimeout(() => person.gender = 'female')
import { observable, observe } from '@nx-js/observer-util'
const person = observable({
name: {
first: 'John',
last: 'Smith'
},
age: 22
})
//
observe(() => console.log(`${person.name.first} ${person.name.last}`))
// logs 'Bob Smith'
setTimeout(() => person.name.first = 'Bob')
import { observable, observe } from '@nx-js/observer-util'
const person = observable({
firstName: 'Bob',
lastName: 'Smith',
get name () {
return `${firstName} ${lastName}`
}
})
observe(() => console.log(person.name))
// logs 'Ann Smith'
setTimeout(() => observable.firstName = 'Ann')
import { observable, observe } from '@nx-js/observer-util'
const users = observable([])
observe(() => console.log(users.join(', ')))
// logs 'Bob'
setTimeout(() => users.push('Bob'))
// logs 'Bob, John'
setTimeout(() => users.push('John'))
// logs 'Bob'
setTimeout(() => users.pop())
import { observable, observe } from '@nx-js/observer-util'
const people = observable(new Map())
observe(() => {
for (let [name, age] of people) {
console.log(`${name}, ${age}`)
}
})
// logs 'Bob, 22'
setTimeout(() => people.set('Bob', 22))
// logs 'Bob, 22' and 'John, 35'
setTimeout(() => people.set('John', 35))
import { observable, observe } from '@nx-js/observer-util'
const defaultUser = observable({
name: 'Unknown',
job: 'developer'
})
const user = observable(Object.create(defaultUser))
// logs 'Unknown is a developer'
observe(() => console.log(`${user.name} is a ${user.job}`))
// logs 'Bob is a developer'
setTimeout(() => user.name = 'Bob')
// logs 'Bob is a stylist'
setTimeout(() => user.job = 'stylist')
// logs 'Unknown is a stylist'
setTimeout(() => delete user.name)
This library detects if you use ES6 or commonJS modules and serve the right format to you. The exposed bundles are transpiled to ES5 to support common tools - like UglifyJS minifying. If you would like a finer control over the provided build, you can specify them in your imports.
@nx-js/observer-util/dist/es.es6.js
exposes an ES6 build with ES6 modules.@nx-js/observer-util/dist/es.es5.js
exposes an ES5 build with ES6 modules.@nx-js/observer-util/dist/cjs.es6.js
exposes an ES6 build with commonJS modules.@nx-js/observer-util/dist/cjs.es5.js
exposes an ES5 build with commonJS modules.If you use a bundler, set up an alias for @nx-js/observer-util
to point to your desired build. You can learn how to do it with webpack here and with rollup here.
Contributions are always welcomed! Just send a PR for fixes and doc updates and open issues for new features beforehand. Make sure that the tests and the linter pass and that the coverage remains high. Thanks!
FAQs
Simple transparent reactivity with 100% language coverage. Made with ES6 Proxies.
The npm package @nx-js/observer-util receives a total of 913 weekly downloads. As such, @nx-js/observer-util popularity was classified as not popular.
We found that @nx-js/observer-util demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.
Security News
NVD’s backlog surpasses 20,000 CVEs as analysis slows and NIST announces new system updates to address ongoing delays.
Security News
Research
A malicious npm package disguised as a WhatsApp client is exploiting authentication flows with a remote kill switch to exfiltrate data and destroy files.