npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

morphmorph

v0.1.3

Published

Mapping, filtering, transforming, and morphing for your objects

Downloads

163

Readme

Morph Morph

Isomorphic transformations. Map, transform, filter, reduce, and morph your objects

tested with jest linted with XO styled with prettier

Getting Started

$ npm i --save morphmorph

and then

const Mapper = require('morphmorph')

const mapper = new Mapper(/* [config] */)

const old = {
  here: {
    there: {
      anywhere: 'Earth'
    }
  }
}

const mappings = [ 'here.there.anywhere:location' ]

const transformation = mapper.map(mappings, old)
// -> { 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 source
]
return mapper.map(mappings, obj)

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',
  type: function (value, mapping, options, sourceObj, targetObj) {
    // 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.substr(0, 4)
    v => v.replace(/\D/g, '') // called first
  ]
}

mapper.map([mapping], { id: 'U1234342'}) // -> 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'
  ],
  type: ([name1, name2, title, occ]) =>
    `${title}. ${name1} ${name2} is a ${occ}`
}

mapper.map([mapping], response).description // -> 'Mr. Mike Fix is a Software Engineer'

Types

You can specify a type system by passing in the types option:

const types = {
  number: Number,
  notNullString: v => (v || '')
}

const mapper = new 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.map(mappings, hairSubscriptionResponse)

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 = new 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 = Mapper.get('key'/*, delimiter */)
const field = get({ key: true })
// -> true
Mapper.assign

Method used to apply a deeply nested field to an object.

const set = Mapper.assign('user.id'/*, delimiter */)
const targetObject = set({}, 1)
// -> { user: { id: 1 } }
Mapper.compose

Method used to apply function compositions

const fun1 = v => `${v}!`
const fun2 = v => v.toUpperCase()
const fun3 = String

const exclaim = Mapper.compose(fun1, fun2, fun3)
exclaim('hey') // -> HEY!

Bonus

Dependencies: None! Size: <2KB gzipped

Examples

See /examples or test/index.spec.js for many examples of how to use MorphMorph.

Thanks