README.MD
# Objectivize
[![Build Status](https://travis-ci.org/ryandabler/objectivize.svg?branch=master)](https://travis-ci.org/ryandabler/objectivize)
[![Coverage Status](https://coveralls.io/repos/github/ryandabler/objectivize/badge.svg?branch=master)](https://coveralls.io/github/ryandabler/objectivize?branch=master)
[![Maintainability](https://api.codeclimate.com/v1/badges/a8cead71f83246940397/maintainability)](https://codeclimate.com/github/ryandabler/objectivize/maintainability)
[![npm](https://img.shields.io/npm/v/objectivize.svg)](https://www.npmjs.com/package/objectivize)
Objectivize is an object utility library.
## Requirements
Objectivize will work on any environment that supports ES6 or higher.
## Installation
### Node
To install the Objectivize library in a Node environment, run
```
npm install objectivize
```
### Browser
Tupos can also be run in a browser environment. The easiest way is to use unpkg and include in a `<script>` tag:
```html
<script src="https://unpkg.com/browse/objectivize@2.0.0/lib/objectivize.min.js">
```
This script will add an `objectivize` key to the `window` object, with the below API exposed through it. Only v2.0.0 or higher are bundled for a browser.
## API
### `get(object, path, notFound?)`
Recurses through an object given a particular path and returns the value found at the end or a fallback value (if one supplied).
A valid path can be a string, symbol, number, or array of any combination of those three types. If the path is a string, it will be split on any `.` to generate an array of keys.
#### Arguments
- `object` _{Object}_: The object to traverse
- `path` _{string | number | symbol | Array<string | number | symbol>}_: The path by which to traverse the object
- `notFound` _{\*}_: The value returned if the path does not resolve in the object
#### Returns
- _{\*}_: The value at the resolved path or the `notFound` value
#### Example
```js
const obj = {
a: {
b: {
c: 1,
d: 2,
},
},
};
get(obj, 'a'); // { b: { c: 1, d: 2 } }
get(obj, 'a.b'); // { c: 1, d: 2 }
get(obj, ['a', 'b', 'd']); // 2
get(obj, 'c'); // undefined
get(obj, 'c', 'fallback'); // 'fallback'
```
### `set(object, path, value)`
Recurses down an object to set a value at the end of a particular path. If at any point the path becomes non-existent, it will be generated during the traversal. If at any point the path hits a non-traversable point (e.g., a number), it will abort.
#### Arguments
- `object` _{Object}_: The object to traverse
- `path` _{string | number | symbol | Array<string | number | symbol>}_: The path by which to traverse the object
- `value` _{\*}_: The value to be set at the resolved path
#### Returns
- _{boolean}_: `true` if the set was successful and `false` otherwise
#### Example
```js
const obj = {
a: {
b: {
c: 1,
d: 2,
},
},
};
set(obj, 'a.b', [1, 2, 3]); // { a: { b: [ 1, 2, 3 ] } }
set(obj, 'a.d', true); // { a: { b: { c: 1, d: 2 }, d: true } }
set(obj, 'a.b.c.d', 'value'); // { a: { b: { c: 1, d: 2 } } }
```
### `update(object, path, updateFn)`
Recurses down an object and passes the particular value into a function and replaces it with that function's return value. It returns `true` to indicate success and `false` otherwise.
#### Arguments
- `object` _{Object}_: The object to traverse
- `path` _{string | number | symbol | Array<string | number | symbol>}_: The path by which to traverse the object
- `updateFn` _{Function(*): *}_: The function called with the value at the resolved path
#### Returns
- _{boolean}_: `true` if the update was successful and `false` otherwise
#### Example
```js
const obj = {
a: {
b: {
c: 1,
d: 2,
},
},
};
const double = n => n;
update(obj, 'a.b.c', double); // { a: { b: { c: 2, d: 2 } } }
update(obj, 'a.b.c.d', double); // { a: { b: { c: 2, d: 2 } } }
```
### `del(object, path)`
Recurses down an object and deletes the property at the given path.
#### Arguments
- `object` _{Object}_: The object to traverse
- `path` _{string | number | symbol | Array<string | number | symbol>}_: The path by which to traverse the object
#### Returns
- _{boolean}_: `true` if the deletion was successful and `false` otherwise
#### Example
```js
const obj = {
a: {
b: {
c: 1,
d: 2,
},
},
};
del(obj, 'a.b.c'); // { a: { b: { d: 2 } } }
```
### `has(object, path)`
Recurses down an object and checks to make sure something exists at the end of the path. The value at the end does not matter; only the existence of the final key is checked.
#### Arguments
- `object` _{Object}_: The object to traverse
- `path` _{string | number | symbol | Array<string | number | symbol>}_: The path by which to traverse the object
#### Returns
- _{boolean}_: `true` if the path resolves and `false` otherwise
#### Example
```js
const obj = {
a: {
b: {
c: 1,
d: 2,
},
},
};
has(obj, 'a.b.c'); // true
has(obj, 'a.b.c.d'); // false
```
### `generate(value, path)`
Given a value and a path, generates a series of nested objects that terminate with the supplied value.
#### Arguments
- `value` _{\*}_: The value to set at the end of the path
- `path` _{string | number | symbol | Array<string | number | symbol>}_: The path down which the value should be set
#### Returns
- _{Object}_: A nested object which terminates at the value
#### Example
```js
generate(1, 'a.b.c'); // { a: { b: { c: 1 } } }
```
### `merge(target, source, onCollision?)`
Deeply merges two objects together. The following method is used in case there is a key collision between the two objects being merged:
- if the values of both are objects, continue merging
- if either one of the values are not objects, pass both into the `onCollision` function
By default, `merge` will override the left object's value with the value on the object being merged into it (similar to `Object.assign`). This can be configured.
The function signature for `onCollision` is
```
(leftObj, rightObj, key) => any
```
where `leftObj` is the current object being merged into (not necessarily the original object passed as the first parameter to `merge`), `rightObj` is the current object being merged (again, not necessarily the second parameter passed into `merge`), and `key` is the key these two objects have in common.
#### Arguments
- `target` _{Object}_: The object being merged into
- `source` _{Object}_: The object being merged
- `onCollision` _{Function(Object, Object, string | symbol): \*}_: The function used to determing merge conflicts
#### Returns
- _{Object}_: The result of the merge operation
#### Example
```js
const left = {
a: {
b: 1,
},
};
const right = {
a: {
b: 2,
c: 3,
},
};
const onCollision = (left, right, key) => [left[key], right[key]];
merge(left, right); // { a: { b: 2, c: 3 } }
merge(left, right, onCollision); // { a: { b: [1, 2], c: 3 } }
```
### `destructure(object, shouldTraverse)`
Will take an object and flatten it into an object of paths and values as the key/value pairs. Any time the function could recurse farther down an object, it calls a configurable `shouldTraverse` parameter to check if it should.
The function signature for `shouldTraverse` is
```
(value, key, obj) => boolean
```
where `value` is the object to potentially traverse into, `key` is its respective key, and `obj` is the object passed into the `destructure` call.
#### Arguments
- `object` _{Object}_: The object to traverse
- `shouldTraverse` _{Function(\*, string | symbol, Object): boolean}_: The path down which the value should be set
#### Returns
- _{Object}_: A flat object of period-separated paths as keys, and their respective terminal values
#### Example
```js
const obj = {
a: {
b: {
c: 1,
d: 2,
},
},
};
const onlyOneKey = obj => Object.keys(obj).length === 1;
destructure(obj); // { 'a.b.c': 1, 'a.b.d': 2 }
destructure(obj, onlyOneKey); // { 'a.b': { c: 1, d: 2 } }
```
### `contains(object, subObject)`
Checks if one object deeply contains another.
#### Arguments
- `object` _{Object}_: The main objct
- `subObject` _{Object}_: The object to check if it is contained in `object`
#### Returns
- _{boolean}_: `true` for containment, `false` otherwise
#### Example
```js
const obj1 = {
a: {
b: {
c: 1,
d: 2,
},
},
};
const obj2 = { b: { c: 1 } };
const obj3 = { c: 2, d: 2 };
contains(obj1, obj2); // true
contains(obj1, obj3); // false
```
### `equals(object1, object2)`
Checks if two objects deeply equal each other.
#### Arguments
- `object1` _{Object}_: An object to check for equality with `object2`
- `object2` _{Object}_: An object to check for equality with `object1`
#### Returns
- _{boolean}_: `true` for equality, `false` otherwise
#### Example
```js
const obj1 = {
a: {
b: {
c: 1,
d: 2,
},
},
};
const obj2 = {
a: {
b: {
c: 1,
d: 2,
},
},
};
const obj3 = {
a: {
b: 5,
},
};
equals(obj1, obj2); // true
equals(obj1, obj3); // false
```
### `keys(object)`
Returns all own (enumerable and non-enumerable) keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<string | symbol>}_: Array of all own keys in the object
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
keys(obj); // [ 'a', 'b', Symbol() ]
```
### `keys.enum(object)`
Returns all own enumerable keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<string>}_: Array of all own enumerable keys
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
keys.enum(obj); // [ 'a', 'b' ]
```
### `keys.names(object)`
Returns all own string (enumerable and non-enumerable) keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<string>}_: Array of all own string keys
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
keys.names(obj); // [ 'a', 'b' ]
```
### `keys.symbols(object)`
Returns all own enumerable keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<symbol>}_: Array of all own symbol keys
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
keys.symbol(obj); // [ Symbol() ]
```
### `values(object)`
Returns all values for own (enumerable and non-enumerable) keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<\*>}_: Array of all own values in the object
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
values(obj); // [ 1, 2, 3 ]
```
### `values.enum(object)`
Returns all values for own enumerable keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<\*>}_: Array of all own enumerable values
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
values.enum(obj); // [ 1, 2 ]
```
### `values.names(object)`
Returns values for all own string (enumerable and non-enumerable) keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<\*>}_: Array of values for all own string keys
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
values.names(obj); // [ 1, 2 ]
```
### `values.symbols(object)`
Returns values for all own enumerable keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<\*>}_: Array of values for all own symbol keys
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
values.symbol(obj); // [ 3 ]
```
### `entries(object)`
Returns all entries for own (enumerable and non-enumerable) keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<[string | symbol, *]>}_: Array of all own entries in the object
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
entries(obj); // [ [ 'a', 1] , [ 'b', 2 ], [ Symbol(), 3 ] ]
```
### `entries.enum(object)`
Returns all entries for own enumerable keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<[string, *]>}_: Array of all own enumerable entries
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
entries.enum(obj); // [ [ 'a', 1 ], [ 'b', 2 ] ]
```
### `entries.names(object)`
Returns entries for all own string (enumerable and non-enumerable) keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<[string, *]>}_: Array of entries for all own string keys
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
entries.names(obj); // [ [ 'a', 1 ], [ 'b', 2 ] ]
```
### `entries.symbols(object)`
Returns entries for all own enumerable keys of a specified object.
#### Arguments
- `object` _{Object}_: The object whose keys should be extracted
#### Returns
- _{Array<[symbol, *]>}_: Array of entries for all own symbol keys
#### Example
```js
const obj = {
a: 1,
b: 2,
[Symbol()]: 3,
};
entries.symbol(obj); // [ [ Symbol(), 3 ] ]
```
### `fromEntries(entries)`
Takes an array of `[key, value]` tuples and constructs an object out of them. Works identically to `Object.fromEntries`.
#### Arguments
- `entries` _{Array<[string | symbol | number, *]>}_: Array of entries for the object
#### Returns
- _{Object}_: An object built from the key/value pairs
#### Example
```js
const entries = [
['key1', 1],
['key2', 2],
];
const object = fromEntries(entries); // { key1: 1, key2: 2 }
```
### `map(object, mapFn)`
Takes an object and a function and manipulates its `[key, value]` pairs.
The function signature for `mapFn` is
```
(key, value, obj) => [newKey, newValue]
```
where `key` and `value` are the current key/value pairs to change, `obj` is the original object, and `[newKey, newValue]` is a tuple of what the new entry should be.
#### Arguments
- `object` _{Object}_: The object to change
- `mapFn` _{Function(string | symbol, \*, Object): [ string | number | symbol, \*]}_: The mapping function
#### Returns
- _{Object}_: The updated object
#### Example
```js
const obj = {
a: 1,
b: 2,
};
const tag = (key, value, object) => [key + value, value * 2];
map(obj, tag); // { a1: 2, b2: 4 }
```
### `mapKeys(object, mapFn)`
Takes an object and a function and manipulates its keys.
The function signature for `mapFn` is
```
(key, value, obj) => newKey
```
where `key` and `value` are the current key/value pairs to change, `obj` is the original object, and `newKey` is the new key to use for that value.
#### Arguments
- `object` _{Object}_: The object to change
- `mapFn` _{Function(string | symbol, \*, Object): string | number | symbol}_: The mapping function
#### Returns
- _{Object}_: The object with updated keys
#### Example
```js
const obj = {
a: 1,
b: 2,
};
const tag = (key, value, object) => key + key;
mapKeys(obj, tag); // { aa: 1, bb: 2 }
```
### `mapValues(object, mapFn)`
Takes an object and a function and manipulates its values.
The function signature for `mapFn` is
```
(value, key, obj) => newValue
```
where `value` and `key` are the current key/value pairs to change, `obj` is the original object, and `newValue` is the new value to use with that key.
#### Arguments
- `object` _{Object}_: The object to change
- `mapFn` _{Function(*, string | symbol, Object): *}_: The mapping function
#### Returns
- _{Object}_: The object with updated values
#### Example
```js
const obj = {
a: 1,
b: 2,
};
const double = (value, key, object) => value * 2;
mapValues(obj, double); // { a: 2, b: 4 }
```
### `find(object, findFn)`
Given an object and a function, returns the first `[key, value]` pair that results in a truthy value.
The function signature for `findFn` is:
```
(key, value, obj) => boolean
```
where `key` and `value` are the current key/value pairs to inspect and `obj` is the original object.
#### Arguments
- `object` _{Object}_: The object to change
- `findFn` _{Function(string | symbol, \*, Object): boolean}_: The finding function
#### Returns
- _{[string | symbol, *]}_: The first `[key, value]` tuple for which `findFn` returned a truthy value
#### Example
```js
const obj = {
a: 1,
b: 2,
c: 3,
};
const findEvenValue = ([key, value]) => value % 2 === 0;
find(obj, findEvenValue); // [ 'b', 2 ]
```
### `findKey(object, findFn)`
Given an object and a function, returns the first key that results in a truthy value.
The function signature for `findFn` is the same as `find()`.
#### Arguments
- `object` _{Object}_: The object to change
- `findFn` _{Function(string | symbol, \*, Object): boolean}_: The finding function
#### Returns
- _{string | symbol}_: The first key for which `findFn` returned a truthy value
#### Example
```js
const obj = {
a: 1,
b: 2,
c: 3,
};
const findEvenValue = ([key, value]) => value % 2 === 0;
findKey(obj, findEvenValue); // 'a'
```
### `findValue(object, findFn)`
Given an object and a function, returns the first value that results in a truthy value.
The function signature for `findFn` is the same as `find()`.
#### Arguments
- `object` _{Object}_: The object to change
- `findFn` _{Function(string | symbol, \*, Object): boolean}_: The finding function
#### Returns
- _{\*}_: The first value for which `findFn` returned a truthy value
#### Example
```js
const obj = {
a: 1,
b: 2,
c: 3,
};
const findEvenValue = ([key, value]) => value % 2 === 0;
findValue(obj, findEvenValue); // 2
```
## License
Objectivze is licensed under the MIT license.