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 🙏

© 2026 – Pkg Stats / Ryan Hefner

flex-merge

v0.1.3

Published

Merge with simple yet powerful rules, for any value - including webpack configurations.

Readme

flex-merge - Merge with simple and powerful customization

There are many JavaScript libraries that merge values. Some of them can be customized to handle very specific scenarios. For example: webpack-merge v4 can merge webpack configurations with customizations. But webpack-merge v5 removed these webpack-specific customizations and replaced them with more generic options. These generic options require more code to customize the merge of webpack configurations.

flex-merge is designed to use very simple generic rules to provide powerful customizations. It's not designed specifically for webpack configurations, but works very well with them. For example, given the following webpack configurations:

const baseConfig = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          "css-loader",
          "sass-loader"
        ]
      },
      // Many other rules
    ]
  },
  // Many other options
}

const extendConfig = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          "style-loader"
        ]
      }
    ]
  }
}

The intention is to merge the /\.scss$/ rule so it uses style-loader on top of css-loader and sass-loader. With flex-merge, it can be done this way:

const options = {
  rules: {
    "$.module.rules": { match: (x, y) => x.test.source === y.test.source } // Elements with the same 'test' value are considered the same element
    "$.module.rules[].use": { notMatched: "prepend" } // Prepend any 'use' elements not found in baseConfig
  }
};
merge(baseConfig, extendConfig, options);

Installation

npm install --save flex-merge

Usage

Basic usage

import { merge } from "flex-merge";

// One source
merge(dest, src, options?);

// Multiple sources
merge([dest, ...src], options?);

Note: values (both dest and src) may be mutated during merge. Create a deep clone first if you want to preserve original values.

Default merge actions

  • Plain objects will be recursively merged by merging every property.
  • Array elements are compared by strict equality ===.
    • If a src element already exists in dest, it will be merged.
    • If a src element doesn't exist in dest, it will be appended.
  • All other values from src will overwrite dest.
    • TODO: Add default merge actions for collection types, such as Set, Map.
    • TODO: Support custom merge functions.

Note: A src property whose value is undefined is considered valid and will overwrite the dest property. To avoid overwriting dest property, the property should not exist in src.

merge({ foobar: "hello" }, { foobar: undefined }); // => { foobar: undefined }
merge({ foobar: "hello" }, { }); // => { foobar: "hello" }

Custom merge options

Provide custom merge rules (scope + action) to customize how values are merged.

const options = {
  rules: {
    "scope1": action1,
    "scope2": action2,
    ...
  }
};
merge(dest, src, options);

Scopes are like JavaScript member access and indexer expressions, with some modifications:

  • $ means root.
  • [] means array elements. Do not use it for member access.

For example, to match bar in { foo: [ { bar: "hello" } ] }, use scope $.foo[].bar. Glob-like patterns are also supported, e.g. $**.bar.

Actions can be simple strings:

  • merge (default) means recursively merge the values.
  • replace means replace dest with src.

Actions can also be objects to customize how to merge arrays:

export type ArrayMergeAction = {
    // Determine whether two elements are equal, default is strict equality '==='
    match?: ((x: any, y: any) => boolean) | null,

    // What to do when an element already exists in `dest`, default is 'merge'
    matched?: "merge" | "replace",

    // What to do when an element does not exist in `dest`, default is 'append'
    notMatched?: "append" | "prepend",
};

When match is set to null, all elements are considered unique. src and dest will be simply concatenated.