ultimate-extend
v2.0.14
Published
Ultimately configurable extend function can be used as always or in any other way you need. Even in objects deep promise iterations.
Downloads
4
Readme
UltimateExtend
Extends target with other object's properties. Works like 'extend' module, but has several updates:
- First argument can be of type Boolean and also UltimateExtend.config ( defines how extend works )
- If objects to extend from are Promises or contain promises in properties you can use Extend.promise instead of Extend. Then it will return promise of Extended object.
Installation
# version 2.x ( alpha )
npm install ultimate-extend --save
# version 1.x ( stable )
npm install [email protected] --save
OLD Readme v1.0.1 - for v2.x see tests TODO: Update this ReadMe
Usage:
// UltimateExtend( [{config|Boolean,ExtendConfig}, ]{target|Object,Function}, ...{options|Object,Function} ) => {Object}
// UltimateExtend.outer( [{config|Boolean,ExtendConfig}, ] ...{options|Object,Function} ) => {Object}
// UltimateExtend.promise( [{config|Boolean,ExtendConfig}, ]{target|Object,Function}, ...{options|Object,Function} ) => {Promise{Object}}
// UltimateExtend.config( {config|Object} ) => {ExtendConfig}
/* --------------------------------- Extend --------------------------------- */
var Extend = require( 'ultimate-extend' );
/* ------------ Simple usage ------------- */
var target = {},
a = { a: { a: [ '1' ] } },
b = { a: { a: [ 2 ], b: 2 } };
Extend( true, target, a, b ); // working as expected
console.log( target ); // => { a: { a: [ 2 ], b: 2 } }
/* ------------ Advanced usage ------------- */
var config = Extend.config({
// if true: deeper objects will be extended too
deep: true,
// if true: allows to extend object with itself ( careful here )
extendSelf: false,
// by default returns property from object to extend from by name
// you can set some special conditions
// e.g. to extend only from all properties with name beginning with underscore, like '_test':
// getOption: ( options, name, config, target ) => {
// if ( name.match( /^_/ )
// || options[ name ] && typeof options[ name ] === 'object'
// ) {
// return options[ name ];
// }
// // undefined must be returned to prevent property extension
// }
// config to extend properties with similar types
extendSimilar: {
Array: ( first, second, config, name ) => first.concat( second )
// Object: ( first, second, config, originMethod ) => ...
// Function: ( first, second, config, originMethod ) => ...
// ... any other type beginning with capital letter ( see 'get-explicit-type' module )
// - replacement occures only when both first and second are having the same type
// - first - target's property
// - second - some object's property ( to extend from )
// - config - current config object
// - config.callOrigin( first, second ) - executes same method from parent config
// - config.newConfig() - creates new ExtendConfig using current one as parent
// - config.level - current deep extend recursion level ( default - 0 )
// - name - current extending property name
}
// executes when first and second properties have different types
// Default( first, second, config, name ) { return newTargetProp }
// returns parent config object ( can not be overwritten )
// getParentConfig()
// base handler to extend first with second ( better not override it )
// use it in extendSimilar if you might receive new value type to extend it as needed by config
// e.g. extendSimilar: {
// // here first and second functions can return any type
// Function: ( first, second, config ) => config.extendProp( first(), second(), config )
// }
// extendProp: ( first, second, config ) => {}
// also you can define extend method which will be used on deeper properties
// so if deep is true then config.extend will handle next deeper extend iterations
// Experimental ( not tested )
// extend: Extend || Extend.promise || YourFunc
});
var target = {}; // renew target; a, b are taken from example above
Extend( config, target, a, b ); // now all arrays are concatenated instead of extending
console.log( target ); // => { a: { a: [ '1', 2 ], b: 2 } }
/* --------------------------------- Extend.promise --------------------------------- */
var Extend = require( 'ultimate-extend' );
var target = {},
a = { a: { a: Promise.resolve( [ '1' ] ) } },
b = { a: { a: [ 2 ], b: new Promise( resolve => setTimeout( () => resolve( 2 ), 500 ) ) } };
Extend.promise( true, target, a, b )
.then( () => {
console.log( target ); // => { a: { a: [ 2 ], b: 2 } }
});
/* --------------------------------- Extend.outer --------------------------------- */
// Extend.outer extends two variables as if they were in extending objects
var Extend = require( 'ultimate-extend' );
var config = Extend.config({
Array: ( first, second ) => first.concat( second ),
Default( first, second, config, name ) {
if ( !first ) return config.callOrigin( first, second, config, name );
if ( !Array.isArray( first ) ) first = [ first ];
if ( !Array.isArray( second ) ) second = [ second ];
return config.extendProp( first, second, config );
}
});
var a = [ 0, 1 ],
b = 2;
Extend.outer( config, a, b ) => [ 0, 1, 2 ]
( Extend( config, {}, { outer: a }, { outer: b } ) ).outer => [ 0, 1, 2 ]
/* --------------------------------- Extend.config --------------------------------- */
// Extend.config can be produced from other configs using config.newConfig( configObj )
// to execute method from origin ( parent ) config use config.callOrigin( ...{ same arguments } )
// config.callOrigin() - here 3rd argument will always be replaced with config which called this method
var Extend = require( 'ultimate-extend' );
var config = Extend.config({
Default: ( first, second, config, name ) => {
return second + 1;
}
});
var newConfig = config.newConfig({
Default: ( first, second, config, name ) => {
return config.callOrigin( first, second, config, name ) + 2;
}
});
console.log( Extend( newConfig, {}, { a: 1 } ) ); // { a: 4 }