Skip to content

Commit

Permalink
Change the API of converter
Browse files Browse the repository at this point in the history
  • Loading branch information
sttk committed Apr 12, 2017
1 parent 37151b0 commit cfddead
Show file tree
Hide file tree
Showing 8 changed files with 514 additions and 271 deletions.
66 changes: 38 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ Usage
var src = { a: 1, b: { b1: 'bbb' } };
var dst = { a: 0 };

copyProps(src, dst, function(value, keychain) {
if (keychain === 'a') {
return value * 2;
copyProps(src, dst, function(srcInfo) {
if (srcInfo.keyChain === 'a') {
return srcInfo.value * 2;
}
if (keychain === 'b.b1') {
return value.toUpperCase();
if (srcInfo.keyChain === 'b.b1') {
return srcInfo.value.toUpperCase();
}
});
// => { a: 2, b: { b1: 'BBB' } }
Expand Down Expand Up @@ -99,11 +99,11 @@ Usage
var src = { a: 'A', b: undefined, c: null, d: 1 };
var dst = { a: 'a', b: 'b', c: 'c' };
copyProps(src, dst, function(value, key) {
if (key === 'd') {
copyProps(src, dst, function(srcInfo) {
if (srcInfo.keyChain === 'd') {
return undefined;
} else {
return value;
return srcInfo.value;
}
});
// => { a: 'A', b: 'b', c: null }
Expand All @@ -115,13 +115,12 @@ Usage
var src = { a: 1, b: 2 };
var dst = {};
copyProps(src, dst, function(srcval, srckey, dstkey, dstval, dstParent) {
var key = dstkey.split('.').pop();
Object.defineProperty(dstParent, key, {
copyProps(src, dst, function(srcInfo, dstInfo) {
Object.defineProperty(dstInfo.parent, dstInfo.key, {
writable: false,
enumerable: true,
configurable: false,
value: srcval * 2
value: srcInfo.value * 2
})
}); // => { a: 2, b: 4 }
Expand All @@ -139,15 +138,15 @@ 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.

* **Arguments:**
**Arguments:**

* **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] : copys reversively from dst to src and returns src object. `fromto` is also reversively used from value to key. This default value is `false`. (optional)
* **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] : copys reversively from dst to src and returns src object. `fromto` is also reversively used from value to key. This default value is `false`. (optional)

* **Return** [object] : *dst* object after copying.
**Return** [object] : *dst* object after copying.

#### *Format of fromto*

Expand All @@ -166,19 +165,30 @@ copyProps(src, dst, {

#### *API of converter*

**<u>converter(srcValue, srcKeychain, dstKeyChain, dstValue, dstParent) => any</u>**
**<u>converter(srcInfo, dstInfo) => any</u>**

*converter* is a function to convert terminal values of propeerties of *src*.

* **Arguments:**
**Arguments:**

* **srcValue** [any] : a source property value to be converted.
* **srcKeychain** [string] : a source property key string concatenated with dots.
* **dstKeychain** [string] : a destination property key string concatenated with dots.
* **dstValue** [any] : a destination property value before copying.
* **dstParent** [object] : the destination node object which has the copied property.
* **srcInfo** [object] : an object which has informations about the current node of *src*. This object has following properties:

* **Return:** [any] : 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.
* **value** : The value of the current node.
* **key** : The key name of the current node.
* **keyChain** : The full key of the current node concatenated with dot.
* **depth** : The depth of the current node.
* **parent** : The parent node of the current node.

* **dstInfo** [object] : an object which has informations about the current node of *dst*. This object has following properties:

* **value** : The value of the current node.
* **key** : The key name of the current node.
* **keyChain** : The full key of the current node concatenated with dot.
* **depth** : The depth of the current node.
* **parent** : The parent node of the current node.


**Return:** [any] : 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.

License
-------
Expand All @@ -189,7 +199,7 @@ This program is free software under [MIT][mit-url] License.
See the file LICENSE in this distribution for more details.

[repo-url]: https://github.com/sttk/copy-props/
[npm-img]: https://img.shields.io/badge/npm-v1.6.0-blue.svg
[npm-img]: https://img.shields.io/badge/npm-v2.0.0-blue.svg
[npm-url]: https://www.npmjs.org/package/copy-props/
[mit-img]: https://img.shields.io/badge/license-MIT-green.svg
[mit-url]: https://opensource.org/licenses.MIT
Expand Down
53 changes: 42 additions & 11 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,25 @@ function copyWithFromto(value, keyChain, nodeInfo) {
dstKeyChains = [dstKeyChains];
}

var srcInfo = {
keyChain: keyChain,
value: value,
key: nodeInfo.name,
depth: nodeInfo.depth,
parent: nodeInfo.parent,
};

for (var i = 0, n = dstKeyChains.length; i < n; i++) {
setDeep(nodeInfo.dest, dstKeyChains[i], function(dstValue, dstParent) {
return nodeInfo.convert(value, keyChain, dstKeyChains[i], dstValue,
dstParent);
setDeep(nodeInfo.dest, dstKeyChains[i], function(parent, key, depth) {
var dstInfo = {
keyChain: dstKeyChains[i],
value: parent[key],
key: key,
depth: depth,
parent: parent,
};

return nodeInfo.convert(srcInfo, dstInfo);
});
}
}
Expand All @@ -100,17 +115,33 @@ function copyWithoutFromto(value, keyChain, nodeInfo) {
return;
}

setDeep(nodeInfo.dest, keyChain, function(dstValue, dstParent) {
return nodeInfo.convert(value, keyChain, keyChain, dstValue, dstParent);
var srcInfo = {
keyChain: keyChain,
value: value,
key: nodeInfo.name,
depth: nodeInfo.depth,
parent: nodeInfo.parent,
};

setDeep(nodeInfo.dest, keyChain, function(parent, key, depth) {
var dstInfo = {
keyChain: keyChain,
value: parent[key],
key: key,
depth: depth,
parent: parent,
};

return nodeInfo.convert(srcInfo, dstInfo);
});
}

function newObject() {
return {};
}

function noop(v) {
return v;
function noop(srcInfo) {
return srcInfo.value;
}

function onlyValueIsString(obj) {
Expand Down Expand Up @@ -148,13 +179,13 @@ function invert(fromto) {
}

function setDeep(obj, keyChain, valueCreator) {
_setDeep(obj, keyChain.split('.'), valueCreator);
_setDeep(obj, keyChain.split('.'), 1, valueCreator);
}

function _setDeep(obj, keyElems, valueCreator) {
function _setDeep(obj, keyElems, depth, valueCreator) {
var key = keyElems.shift();
if (!keyElems.length) {
var value = valueCreator(obj[key], obj);
var value = valueCreator(obj, key, depth);
if (value !== undefined) {
obj[key] = value;
}
Expand All @@ -164,7 +195,7 @@ function _setDeep(obj, keyElems, valueCreator) {
if (!isPlainObject(obj[key])) {
obj[key] = {};
}
_setDeep(obj[key], keyElems, valueCreator);
_setDeep(obj[key], keyElems, depth + 1, valueCreator);
}

function setParentEmptyObject(obj, fromto) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "copy-props",
"version": "1.6.0",
"version": "2.0.0",
"description": "Copy properties deeply between two objects.",
"main": "index.js",
"files": [
Expand Down
12 changes: 5 additions & 7 deletions test/copy-props-args.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,7 @@ describe('Arguments', function() {
it('Should succeed when 3rd arg is a function', function(done) {
var src = { a: 1, b: { c: 2 } };
var dst = { a: 10, b: { d: 20 } };
var converter = function(value) {
return value * 2;
};
var converter = function(srcInfo) { return srcInfo.value * 2; };
var expected = { a: 2, b: { c: 4, d: 20 } };
expect(copyProps(src, dst, converter)).to.deep.equal(expected);
done();
Expand Down Expand Up @@ -137,8 +135,8 @@ describe('Arguments', function() {
var dst = { A: 10, B: { D: 20 } };
var fromto = { a: 'A', 'b.c': 'B.C' };
var expected = { A: 2, B: { C: 4, D: 20 } };
expect(copyProps(src, dst, fromto, function(value) {
return value * 2;
expect(copyProps(src, dst, fromto, function(srcInfo) {
return srcInfo.value * 2;
})).to.deep.equal(expected);
done();
});
Expand Down Expand Up @@ -178,7 +176,7 @@ describe('Arguments', function() {
var src = { a: 1, b: { c: 2 } };
var dst = { A: 10, B: { D: 20 } };
var fromto = { a: 'A', 'b.c': 'B.C', 'b.d': 'B.D' };
var converter = function(value) { return value * 2; };
var converter = function(srcInfo) { return srcInfo.value * 2; };
var expected = { a: 20, b: { c: 2, d: 40 } };
expect(copyProps(src, dst, fromto, converter, true))
.to.deep.equal(expected);
Expand All @@ -189,7 +187,7 @@ describe('Arguments', function() {
var src = { a: 1, b: { c: 2 } };
var dst = { A: 10, B: { D: 20 } };
var fromto = { a: 'A', 'b.c': 'B.C', 'b.d': 'B.D' };
var converter = function(value) { return value * 2; };
var converter = function(srcInfo) { return srcInfo.value * 2; };
var expected = { A: 2, B: { C: 4, D: 20 } };
expect(copyProps(src, dst, fromto, converter, undefined))
.to.deep.equal(expected);
Expand Down
Loading

0 comments on commit cfddead

Please sign in to comment.