
Security News
Feross on the 10 Minutes or Less Podcast: Nobody Reads the Code
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.

An immutable merge util for state management.
Mergerino works very well with the meiosis state management pattern and is offered as a setup option.
Click here to see available builds of mergerino on npm.
import merge from 'https://unpkg.com/mergerino?module'
const state = {
user: {
name: 'John',
weight: 180,
age: 34,
height: 177
},
other: {
many: true,
properties: true
}
}
const newState = merge(state, {
user: {
name: 'Bob',
weight: undefined,
age: age => age / 2
},
other: () => ({ replaced: true })
})
/*
result = {
user: {
name: 'Bob',
age: 17,
height: 177
},
other: {
replaced: true
}
}
*/
state is left intactstate that your patch instruction touched will be shallow copied into newState<script src="https://unpkg.com/mergerino"></script>
<script>
const state = {
user: {
name: 'John',
weight: 180,
age: 34,
height: 177
},
other: {
many: true,
properties: true
}
}
const newState = mergerino(state, {
user: {
name: 'Bob',
weight: undefined,
age: function(age) {
return age / 2
}
},
other: function() {
return { replaced: true }
}
})
/*
result = {
user: {
name: 'Bob',
age: 17,
height: 177
},
other: {
replaced: true
}
}
*/
</script>
Mergerino is made up of a single function merge(target, ...patches).
Patches in mergerino are expressed as plain JavaScript objects:
merge(state, { I: { am: { just: { an: 'object' } } } })
Mergerino merges immutably meaning that the target object will never be mutated (changed). Instead each object along the path your patch specifies will be shallow copied into a new object.
The advantage of this is that patch operations are relatively quick because they only copy the parts of the object that are touched.
This means you can use strict equality (===) to determine where an object was changed by a patch operation:
const state = { obj: {} }
const newState = merge(state, { newProp: true })
console.log(state === newState) // false
console.log(state.obj === newState.obj) // true
If you want to fully remove a property from an object specify undefined as the value.
const state = { deleteMe: true }
const newState = merge(state, { deleteMe: undefined })
console.log(state) // { deleteMe: true }
console.log(newState) // {}
Use null instead of undefined if you don't want the key to be deleted.
If you want to replace a property based on its current value, use a function.
const state = { age: 10, obj: { foo: 'bar' } }
const newState = merge(state, { age: x => x * 2, obj: () => ({ replaced: true }) })
console.log(state) // { age: 10, obj: { foo: 'bar' } }
console.log(newState) // { age: 20, obj: { replaced: true } }
If you pass a function it will receive the current value as the first argument and the merge function as the second. The return value will be the replacement. The value you return will bypass merging logic and simply overwrite the property. This is useful when you want to replace an object without merging. If you would like to merge from within a function patch then use the merge function provided as the second argument.
You can pass multiple patches in a single merge call, array arguments will be flattened before processing.
All the following are valid:
merge(state, [{}, {}, {}])
merge(state, {}, {}, {})
merge(state, [[[[{}]]]])
merge(state, [{}], [{}], [{}])
Another nice side effect of flattening array arguments is that you can easily add conditions to your patches using nested arrays:
merge(state, [
{ week: 56 },
state.age < 10 && { child: true },
state.job === 'programmer' && [
state.promote && { promoted: true },
!state.salaryPaid && { schedulePayment: true }
]
])
If all the above conditions are false (except the job check) the final patch array before flattening will look like this:
patches === [{ week: 56 }, false, [false, false]]
Since falsy patches are ignored only { week: 56 } will be merged.
Another option is to use the spread operator to combine multiple patches into one, but it's harder/messier to write conditions using this technique as you can see:
merge(state, {
{ week: 56 },
...(state.age < 10 ? { child: true } : {}),
...(state.job === 'programmer'
? {
...(state.promote ? { promoted: true } : {}),
...(!state.salaryPaid ? { schedulePayment: true } : {})
}
: {})
})
Mergerino can be used as a reducer where patches are fed into a function which is then applied to a central state object. In these cases you may not have a reference to the full state object to base your patch on.
In order to help in this scenario mergerino supports passing a function as a top level patch. This function acts exactly the same as a function passed to a specific property. It receives the full state object as the first argument, the merge function as the second.
// state-manager.js
let state = { count: 10 }
const update = patch => (state = merge(state, patch))
// other.js
update({ newProp: true })
// want to use value of count to patch
update((state, m) => m(state, { double: state.count * 2 }))
// back in state-manager.js
console.log(state) // { count: 10, newProp: true, double: 20 }
// if you don't use the merge function the top level object will be replaced
update(state => ({}))
console.log(state) // {}
Check out patchinko by Barney Carroll. It was a huge inspiration for mergerino.
It takes a much more explicit approach to signaling patch operations and has some interesting API options.
FAQs
immutable state merge util
We found that mergerino 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
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.

Research
/Security News
Campaign of 108 extensions harvests identities, steals sessions, and adds backdoors to browsers, all tied to the same C2 infrastructure.

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