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

merge-by-template

v0.1.4

Published

A library for generating custom deep-merging functions, that merge data structures according to a set of (nested) rules that you specify.

Downloads

12

Readme

merge-by-template

A library for generating custom deep-merging functions, that merge data structures according to a set of (nested) rules that you specify.

This module is still a work-in-progress! It's already usable in production code, but the documentation is still rough, it may contain the occasional bug, and its API might still change in the future.

Example

A runnable version of this example (and more examples) can be found in example.js in this project's repository.

First, you define a merging template, which results in a custom merging function:

const mergeByTemplate = require("merge-by-template");

let mergeConfiguration = mergeByTemplate.createMerger({
	/* `null` makes it explicit that this property should be overridden as a single value,
	   despite being an object - but leaving the property out entirely would have had the
	   same result, so this is strictly for readability */
	database: null,
	scripts: {},
	accessList: [],
	powerLevel: (a, b) => a + b
});

Then, you use that with two or more input values (eg. objects):

let defaultConfiguration = {
	database: {
		type: "socket",
		path: "/default"
	},
	scripts: {
		test: "echo 'no test configured'",
		publish: "npm publish"
	},
	accessList: [
		"maintainer-bot"
	],
	powerLevel: 8999
};

let customConfiguration = {
	database: {
		hostname: "localhost",
		port: "1234",
		username: "hello",
		password: "world"
	},
	scripts: {
		test: "node test.js",
		build: "node build.js"
	},
	accessList: [
		"real-person"
	],
	powerLevel: 2
};

console.log(mergeConfiguration([ defaultConfiguration, customConfiguration ]));

... and the result of that is a value that's been deep-merged according to your specifications:

{
  database: {
    hostname: 'localhost',
    port: '1234',
    username: 'hello',
    password: 'world'
  },
  scripts: {
    test: 'node test.js',
    publish: 'npm publish',
    build: 'node build.js'
  },
  accessList: [ 'maintainer-bot', 'real-person' ],
  powerLevel: 9001
}

Rules

This section will be expanded in the future.

The basic principle: Regardless of how many values you pass into the custom merging function, it will always merge them per 2. So if you pass in [ a, b, c ] then it will first merge b onto a, and then merge c onto the result of the b -> a merger. The B side always takes precedence in the default merging strategies.

Rules can be nested to any depth (until you hit the runtime's stack size limit, anyway). This allows merging complex nested data structures.

For now, a quick listing of rule syntax:

  • No rule specified (or explicit null or undefined specified): One value overrides the other in full, even if that value is an object or array.
  • Object specified: The input values are expected to be plain objects, and each property will be merged/overridden individually.
    • Empty object: This means all properties are merged according to "No rule specified", ie. the value of one object's property overrides the other.
    • Object with rules: Each specified property is merged according to whatever rule syntax is used for that property. Unspecified properties are overridden according to "No rule specified".
  • Empty array specified: The input values are expected to be arrays, and they will be concatenated together.
  • Array with items specified: Each item is treated as a positional rule. So if you specify an array with two rules, the first item of each input array gets merged according to the first rule, the second item of each input array according to the second rule, and so on. Any surplus items for which no rule exists, are overridden according to "No rule specified".
  • Function specified: The function is called with (a, b) as arguments, and is expected to return whatever the merge result should be. This lets you implement any custom merging logic, at any level in the data structure.