UNPKG

objtools

Version:

Various utility functions for working with object, including object merging, inheritance, deep copying, etc.

273 lines (221 loc) 6.31 kB
# objtools objtools provides several utility functions for working with structured objects. Basic examples of how to use are provided below. See the `docs` directory for full information. ## Utility Functions ```javascript var objtools = require('objtools'); // Check whether a value should be treated as a scalar entity objtools.isScalar(val) // Faster equivalents to lodash objtools.isPlainObject(val) objtools.isEmpty(val) // Faster type-specific isEmpty variants objtools.isEmptyObject(val) objtools.isEmptyArray(val) // Check whether two objects deeply equal each other objtools.deepEquals(a, b) // Check whether two scalars equal each other (mostly equivalent to ===) // but handles dates objtools.scalarEquals(a, b) // Make a duplicate of an object without references to the original objtools.deepCopy(obj) // Given an object, create a mapping from dotted paths to values objtools.collapseToDotted({ foo: { bar: { baz: 123 } } }) // -> { 'foo.bar.baz': 123 } // Has additional options, see docs directory for details // Checks if all fields in the query match corresponding fields in // the dotted object objtools.matchDottedObject({ 'foo.bar': 123, baz: 456 }, { 'foo.bar': 123 } ) // Checks if all fields in the query match corresponding fields in // the object objtools.matchObject( { foo: { bar: 123} }, { 'foo.bar': 123 } ); // Update the destination object in-place to match the source object. This // also takes a third argument of hooks to register while traversing. See // the docs for details. objtools.syncObject( { /* destination object */ }, { /* source object */ } ); // Recursively merge source objects into a base object objtools.merge( { 'characters': [ { 'name': 'barney' }, { 'name': 'fred' } ] }, { 'characters': [ { 'age': 36 }, { 'age': 40 } ] }, { 'characters': [ { 'height': '5\'4"' }, { 'height': '5\'5"' } ] } ) // => { 'characters': [ // { 'name': 'barney', 'age': 36, 'height': '5\'4"' }, // { 'name': 'fred', 'age': 40, 'height': '5\'5"' } // ] } // Get duplicates in an array objtools.getDuplicates([ 'a', 'b', 'a', 'c', 'c' ]); // => [ 'a', 'c' ]; // Get a structured diff of collections objtools.diffObjects({ a: 'b', c: 'd', e: 'f', g: 'h', i: { j: 'k' }, l: { m: 'n', o: { p: 'q' } } }, { a: 'b', c: 1, e: 'f', g: { h: true }, i: { k: 'j' }, l: { m: 'nop' } }) // => { // c: [ 'd', 1 ], // g: [ 'h', { h: true } ], // i: [ { j: 'k' }, { k: 'j' } ], // l: { // m: [ 'n', 'nop' ], // o: [ { p: 'q' }, null ] // } // }; // Get a structured diff of objects and scalars const result = objtools.diffObjects({ a: 'b', c: 'd', e: 'f', g: 'h', i: { j: 'k' }, l: { m: 'n', o: { p: 'q' } } }, { a: 'b', c: 1, e: 'f', g: { h: true }, i: { k: 'j' }, l: { m: 'nop' } }, 'scalar'); const expected = _.extend([ null, null, 'scalar' ], { a: [ 'b', 'b', null ], c: [ 'd', 1, null ], e: [ 'f', 'f', null ], g: [ 'h', { h: true }, null ], i: [ { j: 'k' }, { k: 'j' }, null ], l: { m: [ 'n', 'nop', null ], o: [ { p: 'q' }, null, null ] } }); _.isEqual(result, expected); // => true // Get a consistent hash of an object or primitive which is unlikely to conflict with other objects const obj = { a: 1, b: '2' }; let hash = objtools.objectHash(obj); // Long hex string ``` ## Path Functions These functions involve "object paths". An object path is a dot-separated key specifying a field in an object. For example, in this object: ```javascript var obj = { foo: { bar: [ 1, 2, 3 ] } }; ``` The path to `2` is `foo.bar.1` . Examples of the path functions: ```javascript objtools.getPath(obj, 'foo.bar.1'); // gets 2 objtools.setPath(obj, 'foo.biz', 4); // equivalent to obj.foo.biz = 4 objtools.deletePath(obj, 'foo.biz'); // equivalent to delete obj.foo.biz objtools.dottedDiff({ // returns an array of the shortest diff paths a: { b: 'c', d: { e: 'f' } }, d: 'efg' }, { a: { b: 'c', d: true }, d: 'e', f: 'g' }); // => [ 'a.d', 'd', 'f' ]; ``` ## Masks A "mask" is a structured mapping from keys to boolean `true`. For example, take this object: ```javascript { foo: { bar: { baz: 12, biz: 'test123', buz: 'bip' } } } ``` A mask that matches only the `biz` field would be: ```javascript { foo: { bar: { biz: true } } } ``` A mask that matches anything inside the `bar` object would be: ```javascript { foo: { bar: true } } ``` A mask that matches all fields is simply `true`, whereas a mask that matches no fields is `false`. Masks can also contain wildcards. For example, a mask that matches everything in the `bar` object except for `baz` is: ```javascript { foo: { bar: { _: true, baz: false } } } ``` Arrays can also be used as aliases for wildcards. They are converted to underscore wildcards on instantiation. These two masks are equivalent: ```javascript { _: { foo: true, bar: true } } [ { foo: true, bar: true } ] ``` These are some of the functions that can be performed on masks. See the docs directory for details. This is not a complete list. ```javascript var ObjectMask = require('objtools').ObjectMask; // Create a mask var mask = new ObjectMask({ foo: true, bar: { biz: { buz: true } } }); // Filter an object by the mask // Takes additional options, see docs for details mask.filterObject(obj) // Get a subcomponent of a mask mask.getSubMask('bar.biz') // { buz: true } // Check to see if the mask allows a given path mask.checkPath('bar.biz.buz') // Convert an ObjectMask object back into a plain object mask.toObject() // Validate a mask according to strict rules (only objects, arrays, and booleans) mask.validate() // List all fields in an object restricted by a mask mask.getMaskedOutFields(obj) // Returns true if all fields in the object are allowed by the mask mask.checkFields(obj) // Combine two or more masks such that the resulting mask matches everything that either // of the source masks match (ie, a logical OR) ObjectMask.addMasks(mask, mask2, ...) // Combine two or more masks such that the result mask matches only what ALL of the // source masks match (ie, a logical AND) ObjectMask.andMasks(mask, mask2, ...) // Invert a mask (new mask matches all unmatched paths, doesn't match all matched paths) // Similar to logical 'not' ObjectMask.invertMask(mask); ```