
Security News
Axios Supply Chain Attack Reaches OpenAI macOS Signing Pipeline, Forces Certificate Rotation
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.
No-nonsense State Management! No more boilerplate hell :) Now supports stores and signals! This library is entirely framework agnostic.
Signals are pretty standard to how they exist in other libraries, except they also provide the addListener and removeListener methods.
import {Signal} from 'jabr'
const [get, set, addListener, removeListener] = new Signal(52/* Initial value*/)
console.log(get()) // logs 52
set(7)
console.log(get()) // logs 7
const ourListener = (newValue, oldValue) => {
console.log('New Value: ' + newValue)
console.log('Old Value: ' + oldValue)
}
addListener(ourListener)
set(8) // Now our listener is called, logging our old and new values
removeListener(ourListener)
set(9) // Nothing happens because we removed our listener
We can also just use our signal like a normal variable using the property access. We can also use the object destructuring syntax, which has some benefits over the array destructuring syntax like the ".self" property (which allows us to create a reference to our signal object). Here's a demo of the object destructuring syntax:
const {get: getColor, set: setColor, addListener: addColorListener, self: colorSignal} = new Signal('blue')
addColorListener(color => {
console.log("Got a new color!:", color)
})
setColor('green') // Logs "Got a new color!: green"
getColor() // returns "green"
Now we can pass around our signal to other parts of our code without needing to break up our declaration into multiple lines (by first declaring the signal variable and then destructuring it after). The list of properties are: .get(), .set(), .addListener(), .removeListener(), .self, .initial, .removeAllListeners(), .resetValue(). Another benefit of this syntax compared to array destructuring is that it's not based on the order that you declare your variables, and it's future proof as new properties and methods are added to the signal object.
Store stores are very simple, first we create a store object.
import {Store} from 'jabr'
const store = new Store()
This store object is used just like any other object in Javascript. We can read and modify properties without any special methods.
store.a = 12
console.log(store) // Logs 12
Now the magic* here is that we can attach listeners to our store. Whenever we modify the store our callback function is called with the new data. Let's look at an example:
store.on('a', value => {
console.log(value)
})
store.a = 12 // Logs 12
You can listen to all properties by supplying * instead of the property name. Store triggers the callback function without requiring us to call any methods. It does this by using the Proxy API under the hood, but you don't need to worry about that unless your runtime doesn't support it (all modern Javascript Environments do).
We can intialize our store by supplying it with an object in the constructor.
import {Store} from 'jabr'
const store = new Store({b: "Long John Silvers"})
console.log(store.b) // Logs "Long John Silvers"
Our store can automatically generate signals for us for any given property using the .getSignal method
import {Store} from 'jabr'
const store = new Store({b: "Long John Silvers"})
console.log(store.getSignal('b')) // returns a Signal object that always syncs with our store's 'b' property.
You can also use $ followed by the property name as a syntactical shorthand:
import {Store} from 'jabr'
const store = new Store({b: "Long John Silvers"})
console.log(store.$b) // returns a Signal object that always syncs with our store's 'b' property.
You can pass additional options for each store property by passing a map of option objects for each property. There are a number of features you can supply, including data validation using Sandhands formats, normalization, and more
The format option can be used to ensure your data is properly formatted
import {Store} from 'jabr'
const store = new Store({age: 37}, {age: {format: Number}}) // Our store will now throw an error if we attempt to make age anything besides a number (it can still be deleted)
Passing a function as the compute option will allow you to create a property whose value is computed on the fly.
import {Store} from 'jabr'
const store = new Store({}, {random: {compute: ()=>Math.random()}})
console.log(store.random) // Returns a new random value every time it is accessed
Properties that are computed on the fly cannot be assigned and do not trigger callbacks
When the default option is provided, if our property does not have a value currently and we access it the default value will be returned
We can use the syncToJSON method in order to synchronously save our store to a JSON file. It will also read any existing values in the JSON file.
import {Store, syncToJSON} from 'jabr'
const store = new Store()
syncToJSON(store, 'data.json') // Loads any existing data in data.json (if it exists), overwriting any conflicting properties in the store
store.snack = "cookie" // Synchronously saves this data to the data.json file when we modify the store
As a rule I tend to dislike "magic" in programming. I think this is what makes Ruby on Rails so confusing. All of the functionality in this library is based on Proxies, and I have designed it in a way to be as simple as possible to use and to read my code. I am still sticking to the functional programming paradigm to ensure that my projects avoid bugs & overcomplication. I'd recommend reading more about functional programming, or checking out this projects small and concise source code (warning: it won't make sense until you learn about proxies, but they are a relatively simple extension of functional programming).
FAQs
Framework agnostic Stores & Signals
The npm package jabr receives a total of 32 weekly downloads. As such, jabr popularity was classified as not popular.
We found that jabr demonstrated a healthy version release cadence and project activity because the last version was released less than 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.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.

Security News
Open source is under attack because of how much value it creates. It has been the foundation of every major software innovation for the last three decades. This is not the time to walk away from it.

Security News
Socket CEO Feross Aboukhadijeh breaks down how North Korea hijacked Axios and what it means for the future of software supply chain security.