# copy-props
[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][ci-image]][ci-url] [![Coveralls Status][coveralls-image]][coveralls-url]
Copy properties between two objects deeply.
## Install
To install from npm:
```sh
$ npm i copy-props --save
```
## Usage
Copy _src_ to _dst_ simply (and return _dst_) :
```js
const copyProps = require('copy-props');
var src = { a: 1, b: { b1: 'bbb' }, c: 'ccc' };
var dst = { a: 2, b: { b1: 'xxx', b2: 'yyy' } };
copyProps(src, dst);
// => { a: 1, b: { b1: 'bbb', b2: 'yyy' }, c: 'ccc' }
```
Copy _src_ to _dst_ with property mapping (and return _dst_) :
```js
const copyProps = require('copy-props');
var src = { a: 1, b: { b1: 'bbb' }, c: 'ccc', d: 'ddd' };
var dst = { f: { a: 2, b1: 'xxx', b2: 'yyy' }, e: 'zzz' };
copyProps(src, dst, {
a: 'f.a',
'b.b1': 'f.b1',
'b.b2': 'f.b2',
c: 'f.c',
});
// => { f: { a: 1, b1: 'bbb', b2: 'yyy', c: 'ccc' }, e: 'zzz' }
```
Copy _src_ to _dst_ with convert function (and return _dst_) :
```js
const copyProps = require('copy-props');
var src = { a: 1, b: { b1: 'bbb' } };
var dst = { a: 0 };
copyProps(src, dst, function (srcInfo) {
if (srcInfo.keyChain === 'a') {
return srcInfo.value * 2;
}
if (srcInfo.keyChain === 'b.b1') {
return srcInfo.value.toUpperCase();
}
});
// => { a: 2, b: { b1: 'BBB' } }
```
Can use an array instead of a map as property mapping :
```js
const copyProps = require('copy-props');
var src = { a: 1, b: { c: 'CCC' }, d: { e: 'EEE' } };
var dst = { a: 9, b: { c: 'xxx' }, d: { e: 'yyy' } };
var fromto = ['b.c', 'd.e'];
copyProps(src, dst, fromto);
// => { a: 9, b: { c: 'CCC' }, d: { e: 'EEE' } }
```
Can copy reversively (from _dst_ to _src_) by reverse flag (and return _src_):
```js
const copyProps = require('copy-props');
var src = { a: 1, b: { b1: 'bbb' }, c: 'ccc' };
var dst = { a: 2, b: { b1: 'xxx', b2: 'yyy' } };
copyProps(src, dst, true);
// => { a: 2, b: { b1: 'xxx', b2: 'yyy' }, c: 'ccc' }
```
```js
const copyProps = require('copy-props');
var src = { a: 1, b: { b1: 'bbb' }, c: 'ccc', d: 'ddd' };
var dst = { f: { a: 2, b1: 'xxx', b2: 'yyy' }, e: 'zzz' };
copyProps(
src,
dst,
{
a: 'f.a',
'b.b2': 'f.b2',
c: 'f.c',
},
true
);
// => { a: 2, b: { b1: 'bbb', b2: 'yyy' }, c: 'ccc', d: 'ddd' }
```
If a value of source property is undefined (when not using converter), or a result of converter is undefined (when using converter), the value is not copied.
```js
const copyProps = require('copy-props');
var src = { a: 'A', b: undefined, c: null, d: 1 };
var dst = { a: 'a', b: 'b', c: 'c' };
copyProps(src, dst, function (srcInfo) {
if (srcInfo.keyChain === 'd') {
return undefined;
} else {
return srcInfo.value;
}
});
// => { a: 'A', b: 'b', c: null }
```
You can operate the parent node object directly in converter.
```js
const copyProps = require('copy-props');
var src = { a: 1, b: 2 };
var dst = {};
copyProps(src, dst, function (srcInfo, dstInfo) {
Object.defineProperty(dstInfo.parent, dstInfo.key, {
writable: false,
enumerable: true,
configurable: false,
value: srcInfo.value * 2,
});
}); // => { a: 2, b: 4 }
dst; // => { a: 2, b: 4 }
dst.a = 9;
dst; // -> { a: 2, b: 4 }
```
## API
### copyProps(src, dst [, fromto] [, converter] [, reverse]) => object
Copy properties of _src_ to _dst_ deeply.
If _fromto_ is given, it is able to copy between different properties.
If _converter_ is given, it is able to convert the terminal values.
#### Parameters:
| Parameter | Type | Description |
| :---------- | :-----------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| _src_ | object | A source object of copy. |
| _dst_ | object | A destinate object of copy. |
| _fromto_ | object | array | An object mapping properties between _src_ and _dst_. (Optional) |
| _converter_ | function | A function to convert terminal values in _src_. (Optional) |
| _reverse_ | boolean | True, if copying reversively from dst to src and returns src object. `fromto` is also reversively used from value to key. This default value is `false`. (Optional) |
#### Returns:
_dst_ object after copying.
**Type:** object
- **Format of fromto**
_fromto_ is a non-nested key-value object. And the *key*s are property key chains of _src_ and the *value*s are property key chains of _dst_.
The key chain is a string which is concatenated property keys on each level with dots, like `'aaa.bbb.ccc'`.
The following example copys the value of `src.aaa.bbb.ccc` to `dst.xxx.yyy`.
```js
copyProps(src, dst, {
'aaa.bbb.ccc': 'xxx.yyy',
});
```
_fromto_ can be an array. In that case, the array works as a map which has pairs of same key and value.
- **API of converter**
**converter(srcInfo, dstInfo) : Any**
_converter_ is a function to convert terminal values of propeerties of _src_.
**Parameters:**
| Parameter | Type | Description |
| :-------- | :----: | :---------------------------------------------------------------- |
| _srcInfo_ | object | An object which has informations about the current node of _src_. |
| _dstInfo_ | object | An object which has informations about the current node of _dst_. |
**Return:**
The converted value to be set as a destination property value. If this value is undefined, the destination property is not set to the destination node object.
**Type:** _Any_
- **Properties of srcInfo and dstInfo**
_srcInfo_ and _dstInfo_ has same properties, as follows:
| Property | Type | Description |
| :--------- | :----: | :------------------------------------------------------ |
| _value_ | _Any_ | The value of the current node. |
| _key_ | string | The key name of the current node. |
| _keyChain_ | string | The full key of the current node concatenated with dot. |
| _depth_ | number | The depth of the current node. |
| _parent_ | object | The parent node of the current node. |
## License
MIT
[downloads-image]: https://img.shields.io/npm/dm/copy-props.svg?style=flat-square
[npm-url]: https://www.npmjs.org/package/copy-props
[npm-image]: https://img.shields.io/npm/v/copy-props.svg?style=flat-square
[ci-url]: https://github.com/gulpjs/copy-props/actions?query=workflow:dev
[ci-image]: https://img.shields.io/github/workflow/status/gulpjs/copy-props/dev?style=flat-square
[coveralls-url]: https://coveralls.io/r/gulpjs/copy-props
[coveralls-image]: https://img.shields.io/coveralls/gulpjs/copy-props/master.svg