Created
August 29, 2018 11:17
-
-
Save zaceno/0d7c62be81a845857e755c1378b7dbff to your computer and use it in GitHub Desktop.
Squirrel -- utility for defining transformations of deeply nested objects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Squirrel helps you work with data held in deeply nested objects | |
It creates a mapping based on a given `path`. The mapping transforms a unary function `f` | |
into a function that applies f to the given path of a given object. | |
The path is given as a string, with each nesting level separated by a '.' | |
Some examples: | |
``` | |
const increment = x => x + 1 | |
const fooMap = squirrel('foo') | |
const incrementFoo = fooMap(increment) | |
incrementFoo({foo: 1, bar:1}) // returns: {foo: 2, bar:1} | |
``` | |
Paths are not limited to one level deep: | |
``` | |
const valueMap = squirrel('foo.bar.value') | |
const incrementValue = valueMap(x => x + 1) | |
incrementValue({foo: {bar: {value: 1}, baz: 1}}) | |
// returns: {foo: {bar: {value: 2}, baz: 1}} | |
``` | |
Your path can build on a previously existing mapping: | |
``` | |
const data = { | |
foo: { | |
doors: { | |
'front': 'closed', | |
'back': 'open', | |
'garage': 'closed', | |
} | |
} | |
} | |
const doorMap = squirrel('foo.doors') | |
const setDoorOpen = (doorId, data) => squirrel(doorId, doorMap)(_ => 'open')(data) | |
setDoorOpen('front', data) | |
// returns {foo: {doors: {front: 'open', ...}}} | |
``` | |
Why "Squirrel" ? | |
– Squirrels run up (data-)trees with acorns (=new data) to put in specific places | |
...what *you* call it is up to you of course ;) | |
*/ | |
export default function squirrel (path, map) { | |
const [key, ...rest] = Array.isArray(path) ? path : path.split('.').reverse() | |
if (rest.length) map = squirrel(rest, map) | |
const F = f => x => ({...x, [key]: f(x[key])}) | |
return map ? x => map(F(x)) : F | |
} |
Hi @mshgh thanks for asking and sorry I didn’t notice sooner!
I found the idea too simple to warrant a separate lib, and hence didn’t consider licensing. Of course I’m fine with you using it in whatever way you please, as long as you don’t restrict anyone else from using it in the same way. I e, if you publish it under a license, keep that in mind (use ISC, MIT, BSD3 et c)
You don’t have to credit me, but of course it will make me happy if you do :)
To support array in your data model, replace line 56 with
const F = f => x => Object.assign(Array.isArray(x) ? [] : {}, x, { [key]: f(x[key]) })
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @zaceno,
I have a questions about licensing of this gist? To be more exact can I make it part (copy&paste) of my hyperapp2 modules solution? And make some adjustments to it? If so under what conditions?
Thank you for your answer.