Code Monkey home page Code Monkey logo

merge-options's Introduction

merge-options Build Status Coverage Status XO code style

Merge Option Objects

merge-options considers plain objects as Option Objects, everything else as Option Values.

Install

$ npm install --save merge-options

Usage

const mergeOptions = require('merge-options');

mergeOptions({foo: 0}, {bar: 1}, {baz: 2}, {bar: 3})
//=> {foo: 0, bar: 3, baz: 2}

mergeOptions({nested: {unicorns: 'none'}}, {nested: {unicorns: 'many'}})
//=> {nested: {unicorns: 'many'}}

mergeOptions({[Symbol.for('key')]: 0}, {[Symbol.for('key')]: 42})
//=> {Symbol(key): 42}

Usage with custom config

const mergeOptions = require('merge-options').bind({ignoreUndefined: true});

mergeOptions({foo: 'bar'}, {foo: undefined})
//=> {foo: 'bar'}

API

mergeOptions(option1, ...options)
mergeOptions.call(config, option1, ...options)
mergeOptions.apply(config, [option1, ...options])

mergeOptions recursively merges one or more Option Objects into a new one and returns that. The options are merged in order, thus Option Values of additional options take precedence over previous ones.

The merging does not alter the passed option arguments, taking roughly the following steps:

  • recursively cloning[1] Option Objects and arrays until reaching Option Values
  • copying[1] references to Option Values to the result object
const defaultOpts = {
	fn:      () => false,                  // functions are Option Values
	promise: Promise.reject(new Error()),  // all non-plain objects are Option Values
	array:   ['foo'],                      // arrays are Option Values
	nested:  {unicorns: 'none'}            // {…} is plain, therefore an Option Object
};

const opts = {
	fn:      () => true,                   // [1]
	promise: Promise.resolve('bar'),       // [2]
	array:   ['baz'],                      // [3]
	nested:  {unicorns: 'many'}            // [4]
};

mergeOptions(defaultOpts, opts)
//=>
{
	fn:      [Function],                   // === [1]
	promise: Promise { 'bar' },            // === [2]
	array:   ['baz'],                      // !== [3] (arrays are cloned)
	nested:  {unicorns: 'many'}            // !== [4] (Option Objects are cloned)
}

config

Type: object

config.concatArrays

Type: boolean
Default: false

Concatenate arrays:

mergeOptions({src: ['src/**']}, {src: ['test/**']})
//=> {src: ['test/**']}

// Via call
mergeOptions.call({concatArrays: true}, {src: ['src/**']}, {src: ['test/**']})
//=> {src: ['src/**', 'test/**']}

// Via apply
mergeOptions.apply({concatArrays: true}, [{src: ['src/**']}, {src: ['test/**']}])
//=> {src: ['src/**', 'test/**']}
config.ignoreUndefined

Type: boolean
Default: false

Ignore undefined values:

mergeOptions({foo: 'bar'}, {foo: undefined})
//=> {foo: undefined}

// Via call
mergeOptions.call({ignoreUndefined: true}, {foo: 'bar'}, {foo: undefined})
//=> {foo: 'bar'}

// Via apply
mergeOptions.apply({ignoreUndefined: true}, [{foo: 'bar'}, {foo: undefined}])
//=> {foo: 'bar'}

Related

  • See object-assign if you need a ES2015 Object.assign() ponyfill
  • See deep-assign if you need to do Object.assign() recursively

Notes

  1. copying and cloning take only enumerable own properties into account

License

MIT © Michael Mayer

merge-options's People

Contributors

achingbrain avatar schnittstabil avatar wopian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

merge-options's Issues

[Request] Keep first param reactive like Object.assign

I'm looking for a "deep" Object.assign() that just like object assign will merge things onto the first Param. However, I need this first param (the target) to "be modified" (just like Object.assign) and not become a hard-clone.

Is this possible with your library?

Fails to build on create-react-app: Publish ES5 to NPM

When building a project using merge-options on create-react-app, react-scripts build will give the following error:

> react-scripts build

Creating an optimized production build...
Failed to compile.

Failed to minify the code from this file:

 	./node_modules/merge-options/index.js:11

Read more here: http://bit.ly/2tRViJ9

This link to the create-react-app documentation explains the problem in more detail:

Some third-party packages don't compile their code to ES5 before publishing to npm. This often causes problems in the ecosystem because neither browsers (except for most modern versions) nor some tools currently support all ES6 features. We recommend to publish code on npm as ES5 at least for a few more years.

cjs/esm support breaks IntelliSense of VSCode

from index.js

module.exports = function (...options) {

from index.d.ts

export default function (...options: any[]): any;

VSCode expects the function to exist at default, while in reality, there is no default export.
image

TypeScript is not supported

Hello,
I'd like to use this package with TypeScript, but it's actually impossible, because there isn't any .d.ts file... It would be nice to add them!

npm audit reports this package as problematic for prototype pollution

┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low           │ Prototype pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ merge-options                                                │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ No patch available                                           │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ webpack-command [dev]                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ webpack-command > @webpack-contrib/config-loader >           │
│               │ merge-options                                                │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/717                       │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low           │ Prototype pollution                                          │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ merge-options                                                │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ No patch available                                           │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ webpack-command [dev]                                        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ webpack-command > merge-options                              │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://nodesecurity.io/advisories/717                       │
└───────────────┴──────────────────────────────────────────────────────────────┘

I've checked the dependency in that webpack-command package, it's

"merge-options": "^1.0.0",

Rollup complains

Using rollup when trying to bundle this dep I'm getting:

[!] Error: 'default' is not exported by ../../../node_modules/merge-options/index.js, imported by src/example.js
https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module

Update:

Never mind. It was a misconfiguration 😃

Consideration for Alternate Array Handling

I'd like to propose a method to handle array values differently. It's something that I find lacking in every single merge/deep-copy/extend/assign library I can find; none of them provide a means to concat array values rather than simple overriding them.

It could be possible to create a factory pattern that accepted options for determining behavior. e.g.

const merge = mergeOptions.set({ arrays: 'concat' });
const result = merge({}, {a:[3]}, {a:[1,2]});
// { a: [3, 1, 2] }

That could support multiple different methods (which could even be user-extendible), with the default being the current behavior of right-most replacement as an object value.

Breaking in webpack when ignore node_modules

Hey,

Thanks for the package. I noticed that your es6 in 1.0.0 is not transpiled down to es5. I would suggest using babel to output a dist because most people (like me) ignore node_modules for the transpilation process. Ignoring node_modules helps speed up the build by orders of magnitude.

Cheers!

node 12 support?

v3 of this module refactored to use esm modules and set the engines field to require node >= 14, yet this module is published transpiled to common js so does run on node 12 at least.

If a user has engine-strict = true or is running yarn, it'll fail to install on node 12 even though it will run.

Can the engines field be relaxed? Node 12 is active LTS for another few months and maintenance LTS until spring 2022 so dropping support seems premature.

Refs: ipfs/js-ipfs#3270

undefined values are merged

Based on the following code:

    const merge = require('merge-options');
    const result = merge({value: 10}, {value: undefined});

result.value should be '10', but it is 'undefined'.

Whether it really should return 10 is arguable, so my argument is that {} is functionally equivalent to {value: undefined} when getting a value from on object, so as inputs to merge they should both provide equivalent output. Where they are not functionally equivalent is when iterating the objects keys, but when dealing with options (and being mindful if the distinction between undefined and null) the rule of least surprise (for me at least) is to completely ignore undefined values (but still allow null values to supersede values of lower precedence).

The practical application of this is putting environment variables (which may or may not be defined) as the highest precedence item in the merge, but only if it has been defined.
const port = merge(defaults, {port: process.env.PORT});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.