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

immutable-custom-merge

v0.2.1

Published

Custom deep merging of Immutable data structures

Downloads

3

Readme

npm version Build Status Coverage Status

immutable-custom-merge

Deep merging of Immutable structures with custom per-property merging strategy.

Example usage

import {fromJS} from 'immutable'
import merge from 'immutable-custom-merge'

const object1 = fromJS({
  a: [1, 2, 3],
  b: {
    x: [1, 2, 3],
    y: ['a', 'b'],
  },
  c: [1, 2, 3],
  d: 4,
  e: 5
  
})

const object2 = fromJS({
  a: [3, 4],
  b: {
    x: [3, 4],
    y: ['b', 'c'],
  },
  c: [3, 4],
  d: 8,
  e: 6
})

// defines how properties should be merged in case of collisions
const mergeSchema = {
  a: 'append',        // colliding iterables should be appended
  b: {
    '*': 'union',     // 'union' function will be applied on every key under `b`
  },
  e: (a, b) => a + b  // use custom defined function to merge values under this key
}

// merge two immutable Maps using the schema
const result = merge(object1, object2, mergeSchema)

Result of the above merging would be Immutable Map having this structure:

{
  a: [1, 2, 3, 3, 4],   // colliding array was appended
  b: {
    x: [1, 2, 3, 4],    // union of items
    y: ['a', 'b', 'c']  // union of items
  },
  c: [3, 4, 3],         // no rule - default Immutable merge
  d: 8,                 // no rule for property means later overrides former
  e: 11                 // custom function to solve collisions
}

mergeDeep(val1, val2, schema)

immutable-custom-merge exports just one function. It performs deep merge of val1 into val2, using provided schema to determine how to merge specific keys if there's a collision.

  • val1: required Immutable structure (most typically Map) to be merged with second argument. Beyond Maps it supports other Immutable types where deep merging makes sense.
  • val2: required Immutable structure to be merged into val1
  • schema: structured js object defining merge strategy for specific keys of input parameters. String with the name of one of pre-defined merge functions or custom merge function. If schema is string or function, first two arguments doesn't need to be immutables. If schema is not supplied at all, it falls back to standard immutable mergeDeep function. If schema is not supplied and first argument is non-immutable, it just returns second argument.

Defining merge schema

Basically, you need to specify merge function for certain (sub)keys of your input data that you want to merge differently from how native immutable merge function does it.

Schema bellow only defines special behaviour for sub-key messages. Every other key will be treated as it would be merged by native mergeDeep function.

const mergeSchema = {
  result: {
    messages: 'append'
  } 
}

There are two kinds of merge functions that can be specified in the schema. Pre-defined and custom merge functions. Merge function is called when key (for which it is defined in merge schema) is present in both val1 and val2. Merging function receives values of this keys as it's arguments (first one is val1's, second one is val2's).

Wildcard key

If you need to apply some merge function on every (sub)item, you can specify '*' instead of a key. This is quite usefull in situation when you store similar structured records in Map-like objects (maybe you use normalizr?):

const object1 = fromJS({
  books: {
    '111': {
      id: '111',
      author: '888' 
    },  
    '222': {
      id: '222',
      author: '999' 
    }  
  },
  authors: {
    ...
  }
  
})

You may want to merge book records into your store, but some sources may list a book with more authors so you might need to keep all of them. You would use this schema to merge in new data:

const mergeSchema = {
  books: {
    '*': {
      author: 'union'
    }
  } 
}

Pre-defined merging functions

There are some pre-defined function to choose from:

append

Works with Immutable Iterables. Appends items of second parameter to the end of the first one

const object1 = fromJS({ a: [1, 2, 3] })
const object2 = fromJS({ a: [3, 4] })
const mergeSchema = { a: 'append' }
const result = merge(object1, object2, mergeSchema)

// result: { a: [1, 2, 3, 3, 4] }

prepend

Same as append but items are prepended

const object1 = fromJS({ a: [1, 2, 3] })
const object2 = fromJS({ a: [3, 4] })
const mergeSchema = { a: 'prepend' }
const result = merge(object1, object2, mergeSchema)

// result: { a: [3, 4, 1, 2, 3] }

union

Same as append but only items that are not already in the list are appended

const object1 = fromJS({ a: [1, 2, 3] })
const object2 = fromJS({ a: [3, 4] })
const mergeSchema = { a: 'union' }
const result = merge(object1, object2, mergeSchema)

// result: { a: [1, 2, 3, 4] }

Custom merging functions

Instead of using predefined function, you can supply your own. It will receive two arguments, conflicting values.

const object1 = fromJS({ a: 3 })
const object2 = fromJS({ a: 5 })
const mergeSchema = { a: (a, b) => a + b }
const result = merge(object1, object2, mergeSchema)

// result: { a: 8 }