Morph Morph
Isomorphic transformations. Map, transform, filter, reduce, and morph your objects
Getting Started
$ npm i --save morphmorph
and then
const Mapper = const mapper = /* [config] */ const old = here: there: anywhere: 'Earth' const mappings = 'here.there.anywhere:location' const transformation = mapper// -> { location: 'Earth' }
Creating Transformations
Every transformation can be represented by a mapping passed in as the first parameter
to mapper.map()
. Mappings can either be of type String
or Object
. A mapping such as 'before:after'
is equivalent to: { field: 'before:after' }
Basic
const mappings = 'before:after' 'egg:they.can.be.deeply.nested' // deeply nested target 'data.user.updated:updated' // deeply nested sourcereturn mapper
Functions
When creating a mapping, if you pass a function as the type
parameter,
the function you passed will be called with the following properties to produce
the result:
const mapping = field: 'name' { // value: the value grabbed from the source object // mapping: this specific mapping // options: config you specified by `new Mapper(options)` // sourceObj: object you passed as mapper.map(mapping, sourceObj) // targetObj: object you passed as mapper.map(m, sourceObj, targetObj). Default to `{}` }
Arrays
You can also pass an Array of functions and MapLib
will perform a right-to-left
function composition:
const mapping = field: 'id:pin' type: Number // called last v v // called first mapper // -> 1234
Function Compositions
If you want to do function compositions the traditional way, you can use Mapper.compose(...myFilterFunctions)
. Again it will be a right-to-left composition.
Reductions
By specifying your field
property as an array, you can reduce multiple values into a single one. The values will be included as the first parameter of your type
function. The target field is specified by the last mapping in your array
Example
const response = user: firstName: 'Mike' lastName: 'Fix' professionInfo: title: 'Mr' occupation: 'Software Engineer' const mapping = field: 'user.firstName' 'user.lastName' 'user.professionInfo.title' 'user.professionInfo.occupation' 'description' `. is a ` mapperdescription // -> 'Mr. Mike Fix is a Software Engineer'
Types
You can specify a type system by passing in the types
option:
const types = number: Number v || '' const mapper = types
and then specify which type to use as a string for each mapping:
const mappings = field: 'haircolor' type: 'notNullString' field: 'daysRemaining': type: 'number' return mapper
Note: each function in the type specification is passed the same parameters as the normal type functions
Config
You can pass in a config object to Mapper
to create your own mapping system:
Options
Field | Type | Default |
---|---|---|
types |
Object |
{} |
objDelimiter |
String |
"." |
mapDelimiter |
String |
":" |
preFilters |
Array |
[] |
postFilters |
Array |
[] |
Example
const mapper = objDelimiter: '|' mapDelimiter: '->' types: bool: Boolean preFilters: FILTER_NULL postFilters: REMOVE_PASSWORD // add other fields to your config here
Static methods
Mapper.get
Method used to grab a deeply nested field from an object.
const get = Mapperconst field = // -> true
Mapper.assign
Method used to apply a deeply nested field to an object.
const set = Mapperconst targetObject = // -> { user: { id: 1 } }
Mapper.compose
Method used to apply function compositions
const fun1 = `!`const fun2 = vconst fun3 = String const exclaim = Mapper // -> HEY!
Bonus
Dependencies: None!
Size: <2KB gzipped
Examples
See /examples or test/index.spec.js
for many examples of how to use MorphMorph
.
Thanks
- Mostly Adequate Guide to Functional Programming for examples and reference implementations