
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
A State Manager built for Lean Functional Typescript
Checkout: https://github.com/attack-monkey/Lean-Functional-Typescript
npm i lean-state
import { register } from 'lean-state'
import { register } from 'lean-state'
type Global = {
greeting: string
}
type Listeners =
| 'listener1'
| 'listener2'
| 'listener3'
// register
const global = register<Global, Listeners>()
// set
global.set('greeting').with('hello world')
// get
console.log(
global.get().greeting
)
// get the current and pass to function
global.once(
({ greeting }) => console.log(greeting)
)
// set up a listener...
global
.listenOn('listener1')
.for(['greeting'])
.subscribe(({ greeting }) => console.log('listener1: ' + greeting))
// make changes and the listener will react
global.set('greeting').with('howdy y\'all')
global.set('greeting').with('wassup')
global.set('greeting').with('g\'day mate')
// set up a listener that auto tears down when a condition is no longer met
global
.listenOn('listener2')
.for(['greeting'])
.while(({ greeting }) => greeting !== 'stop listening')
.subscribe(({ greeting }) => console.log('listener2: ' + greeting))
// make changes and both listeners will react
global.set('greeting').with('good day')
// this next change will trigger listener2 to tear down...
global.set('greeting').with('stop listening')
// listeners can also be set up to listen, starting from the next change...
global
.listenOn('listener3')
.fromNext(['greeting'])
.while(({ greeting }) => greeting !== 'stop listening')
.subscribe(({ greeting }) => console.log('listener3: ' + greeting))
// And more changes...
global.set('greeting').with('heeeey!!!')
global.set('greeting').with('stop listening')
Lean-state is a key-value store, so while complex data can be stored at a given key, listeners can only listen to changes at that top-level key.
This isn't really a problem at all - but does change the way you think about listening to changes in data.
If for example a key stores a Record of items - but your app is focused on changes only at a given item - then it's a good idea to also capture which id is being focused on and which id is being changed.
import { register } from 'lean-state'
type Car = {
make: string
color: string
}
type Global = {
cars: Record<string, Car>
lastUpdatedCar: string,
focusOnCar: string
}
type Listeners =
| 'listener1'
| 'listener2'
const global = register<Global, Listeners>()
const listenToAllCarChanges = () => {
global
.listenOn('listener1')
.fromNext(['lastUpdatedCar'])
.subscribe(({ cars, lastUpdatedCar }) =>
console.log(`change to car ${lastUpdatedCar} => ${JSON.stringify(cars[lastUpdatedCar], null, 2)}`)
)
}
const listenToNewFocusCar = (id: string) => {
// Set up the car to focus on
global.set('focusOnCar').with(id)
global
.listenOn('listener2')
// listen to the next change to lastUpdatedCar
.fromNext(['lastUpdatedCar'])
.subscribe(({ cars, focusOnCar, lastUpdatedCar }) => {
if(lastUpdatedCar === focusOnCar) {
console.log(`Focussed car is ${focusOnCar} and it changed to => ${JSON.stringify(cars[focusOnCar], null, 2)}`)
}
})
}
const setInitialData = () => {
global.set('cars').with({
'1': { make: 'Toyota', color: 'red' },
'2': { make: 'Toyota', color: 'blue'}
})
global.set('focusOnCar').with('1')
}
const updateCar = (id: string) => ({
with: (car: Car) => {
global.set('cars').at(id).with(car)
global.set('lastUpdatedCar').with(id)
}
})
// Set up data
setInitialData()
// Set up listeners
listenToAllCarChanges()
listenToNewFocusCar('1')
// Make updates
updateCar('3').with({ make: 'Corvette', color: 'red' })
updateCar('1').with({ make: 'Ferrari', color: 'pink' })
// Change focus car, which re-creates the listener
listenToNewFocusCar('2')
// Make more changes
updateCar('1').with({ make: 'Ferrari', color: 'red' })
updateCar('2').with({ make: 'Lamborgini', color: 'grey' })
FAQs
A simple yet powerful way to manage state and reactive dataflow
We found that lean-state 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.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.