subclassable-object-merger
v1.0.1
Published
An Object.assign() generalization with overridable rules
Downloads
8
Readme
Rationale
The public npm registry contains a plethora of modules implementing deep (recursive) alternatives to the standard Object.assign().
Some of them are basically single functions with fixed logic hardly suitable for any extending, for instance:
- deep-object-merger (just a recursive
Object.assign()
) - multi-merge (+something special about Boolean values)
- object-merger (never mind Booleans, concatenate arrays)
Others offer to set up sophisticated custom rules using some languages other than plain ECMAScript:
- decorated-merger (TypeScript Decorations)
- json-object-merge (JSONPath)
The author of this module needed something very close to the basic naive implementation, but easily customizable by the means of standard ES. This is why subclassable-object-merger
was created.
Installation
npm install subclassable-object-merger
Usage
const {ObjectMerger} = require ('subclassable-object-merger')
const om = new ObjectMerger (
//{override: [
// 'scalar',
// 'array',
// 'object',
//]}
)
const t1 = {
name: 'users',
label: 'System users',
columns: {
id: {TYPE: 'int'},
},
data: [
{id: 1, label: 'admin'}
],
triggers: null,
}
const t2 = {
name: 'users',
label: undefined,
columns: {
id: {AUTO_INCREMENT: true},
label: {TYPE: 'text'},
},
pk: 'id',
data: [
{id: 2, label: 'employee'}
],
triggers: {before_insert: 'RETURN;'},
}
om.merge (t1, t2) /* result:
{
name: 'users',
label: 'System users',
pk: 'id',
columns: {
id: {TYPE: 'int', AUTO_INCREMENT: true},
label: {TYPE: 'text'},
},
data: [
{id: 1, label: 'admin'},
{id: 2, label: 'employee'}
],
triggers: {before_insert: 'RETURN;'},
})
*/
Constructor
May be invoked without parameters or with a single {override}
object.
The override
option
When set, override
must be an array of type names (see getType ()
below) to be forcibly overridden in case of conflict.
In particular, setting {override: ['scalar']}
will lead to merge ({name: 'specific'}, {name: 'default'})
into {name: 'specific'}
instead of throwing an error.
Internals
Instance properties
The only property is sum
: the object mapping type names to corresponding type specific adding functions. Simply put:
this.sum = {
array: (a, b) => a.concat (b),
object: (a, b) => this.merge (a, b),
scalar: (a, b) => a === b ? a : throw Error ()
}
With the override
option, a => a
is set for types listed therein.
Methods
getType (a)
For a given non-null a
, returns:
'array'
ifArray.isArray (a)
'object'
iftypeof a === 'object'
(no advanced checker likeis-plain-obj
noris-plain-object
is in use here)'scalar'
otherwise (e. g. for function valueda
)
add (a, b, k)
Does the main job here: calls getType
for a
and b
and if the results are the same, merges b
into a
; otherwise, throws an error.
When a
or b
is null
or undefined
, returns the other argument (which may be null
or undefined
too).
The k
parameter is a name of the outer objects properties whose values are a
and b
. It doesn't affect the result, but may appear in error messages. Descendant classes may use this argument for some special needs.
merge (a, b)
This top level method copies b
's content into a
by calling add
for each of b
's keys. Both a
and b
must be plain Objects.
Events
ObjectMerger inherits from EventEmitter. Though never using this feature on its own, it may be used as a message box by containing processes.