From 1c2276bdb3a3677379146827be0519ad4e3102e1 Mon Sep 17 00:00:00 2001 From: Eirik Horvath Date: Thu, 21 Dec 2017 15:57:50 +0100 Subject: [PATCH 1/2] Fixed bug where array is not concatted, but rather final value is king. --- lib/nestedObjectAssign.js | 64 ++++++++++++++++++++++++++++++++++++++- package.json | 3 +- src/isArray.js | 3 ++ src/nestedObjectAssign.js | 15 ++++++--- 4 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 src/isArray.js diff --git a/lib/nestedObjectAssign.js b/lib/nestedObjectAssign.js index c551037..8e9e858 100644 --- a/lib/nestedObjectAssign.js +++ b/lib/nestedObjectAssign.js @@ -1 +1,63 @@ -module.exports=function(e){function t(o){if(r[o])return r[o].exports;var n=r[o]={exports:{},id:o,loaded:!1};return e[o].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){"use strict";function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function n(e){for(var t=arguments.length,r=Array(t>1?t-1:0),u=1;u 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n sources[_key - 1] = arguments[_key];\n }\n\n if (!sources.length) return target;\n\n var source = sources.shift();\n\n if ((0, _isObject.isObject)(target) && (0, _isObject.isObject)(source)) {\n for (var key in source) {\n if ((0, _isObject.isObject)(source[key])) {\n if (!target[key]) {\n Object.assign(target, _defineProperty({}, key, {}));\n }\n\n nestedObjectAssign(target[key], source[key]);\n } else if ((0, _isArray.isArray)(source[key])) {\n if (!target[key]) {\n Object.assign(target, _defineProperty({}, key, []));\n }\n\n target[key] = target[key].concat(source[key]);\n } else {\n Object.assign(target, _defineProperty({}, key, source[key]));\n }\n }\n }\n\n return nestedObjectAssign.apply(undefined, [target].concat(sources));\n}\nmodule.exports = exports['default'];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvbmVzdGVkT2JqZWN0QXNzaWduLmpzP2ZmYWMiXSwibmFtZXMiOlsibmVzdGVkT2JqZWN0QXNzaWduIiwidGFyZ2V0Iiwic291cmNlcyIsImxlbmd0aCIsInNvdXJjZSIsInNoaWZ0Iiwia2V5IiwiT2JqZWN0IiwiYXNzaWduIiwiY29uY2F0Il0sIm1hcHBpbmdzIjoiOzs7OztrQkFHd0JBLGtCOztBQUh4Qjs7QUFDQTs7OztBQUVlLFNBQVNBLGtCQUFULENBQTRCQyxNQUE1QixFQUErQztBQUFBLHNDQUFSQyxPQUFRO0FBQVJBLGVBQVE7QUFBQTs7QUFDMUQsUUFBSSxDQUFDQSxRQUFRQyxNQUFiLEVBQ0ksT0FBT0YsTUFBUDs7QUFFSixRQUFNRyxTQUFTRixRQUFRRyxLQUFSLEVBQWY7O0FBRUEsUUFBSSx3QkFBU0osTUFBVCxLQUFvQix3QkFBU0csTUFBVCxDQUF4QixFQUF5QztBQUNyQyxhQUFLLElBQU1FLEdBQVgsSUFBa0JGLE1BQWxCLEVBQXlCO0FBQ3JCLGdCQUFJLHdCQUFTQSxPQUFPRSxHQUFQLENBQVQsQ0FBSixFQUEwQjtBQUN0QixvQkFBSSxDQUFDTCxPQUFPSyxHQUFQLENBQUwsRUFBa0I7QUFDZEMsMkJBQU9DLE1BQVAsQ0FBY1AsTUFBZCxzQkFBd0JLLEdBQXhCLEVBQThCLEVBQTlCO0FBQ0g7O0FBRUROLG1DQUFtQkMsT0FBT0ssR0FBUCxDQUFuQixFQUFnQ0YsT0FBT0UsR0FBUCxDQUFoQztBQUNILGFBTkQsTUFNTyxJQUFJLHNCQUFRRixPQUFPRSxHQUFQLENBQVIsQ0FBSixFQUEwQjtBQUM3QixvQkFBSSxDQUFDTCxPQUFPSyxHQUFQLENBQUwsRUFBa0I7QUFDZEMsMkJBQU9DLE1BQVAsQ0FBY1AsTUFBZCxzQkFBd0JLLEdBQXhCLEVBQThCLEVBQTlCO0FBQ0g7O0FBRURMLHVCQUFPSyxHQUFQLElBQWNMLE9BQU9LLEdBQVAsRUFBWUcsTUFBWixDQUFtQkwsT0FBT0UsR0FBUCxDQUFuQixDQUFkO0FBQ0gsYUFOTSxNQU1BO0FBQ0hDLHVCQUFPQyxNQUFQLENBQWNQLE1BQWQsc0JBQXdCSyxHQUF4QixFQUE4QkYsT0FBT0UsR0FBUCxDQUE5QjtBQUNIO0FBQ0o7QUFDSjs7QUFFRCxXQUFPTixxQ0FBbUJDLE1BQW5CLFNBQThCQyxPQUE5QixFQUFQO0FBQ0giLCJmaWxlIjoiMC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzT2JqZWN0IH0gZnJvbSAnLi9pc09iamVjdCc7XHJcbmltcG9ydCB7IGlzQXJyYXkgfSBmcm9tICcuL2lzQXJyYXknO1xyXG5cclxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gbmVzdGVkT2JqZWN0QXNzaWduKHRhcmdldCwgLi4uc291cmNlcyl7XHJcbiAgICBpZiAoIXNvdXJjZXMubGVuZ3RoKVxyXG4gICAgICAgIHJldHVybiB0YXJnZXQ7XHJcblxyXG4gICAgY29uc3Qgc291cmNlID0gc291cmNlcy5zaGlmdCgpO1xyXG5cclxuICAgIGlmIChpc09iamVjdCh0YXJnZXQpICYmIGlzT2JqZWN0KHNvdXJjZSkpe1xyXG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHNvdXJjZSl7XHJcbiAgICAgICAgICAgIGlmIChpc09iamVjdChzb3VyY2Vba2V5XSkpe1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0YXJnZXRba2V5XSkge1xyXG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odGFyZ2V0LCB7W2tleV06IHt9fSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbmVzdGVkT2JqZWN0QXNzaWduKHRhcmdldFtrZXldLCBzb3VyY2Vba2V5XSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShzb3VyY2Vba2V5XSkpIHtcclxuICAgICAgICAgICAgICAgIGlmICghdGFyZ2V0W2tleV0pIHtcclxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKHRhcmdldCwge1trZXldOiBbXX0pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHRhcmdldFtrZXldID0gdGFyZ2V0W2tleV0uY29uY2F0KHNvdXJjZVtrZXldKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24odGFyZ2V0LCB7W2tleV06IHNvdXJjZVtrZXldfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG5lc3RlZE9iamVjdEFzc2lnbih0YXJnZXQsIC4uLnNvdXJjZXMpO1xyXG59XG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL25lc3RlZE9iamVjdEFzc2lnbi5qcyJdLCJzb3VyY2VSb290IjoiIn0="); + +/***/ }), +/* 1 */ +/***/ (function(module, exports) { + + eval("'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nexports.isObject = isObject;\nfunction isObject(item) {\n return item && (typeof item === 'undefined' ? 'undefined' : _typeof(item)) === 'object' && !Array.isArray(item);\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvaXNPYmplY3QuanM/YzBhOCJdLCJuYW1lcyI6WyJpc09iamVjdCIsIml0ZW0iLCJBcnJheSIsImlzQXJyYXkiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O1FBQWdCQSxRLEdBQUFBLFE7QUFBVCxTQUFTQSxRQUFULENBQWtCQyxJQUFsQixFQUF1QjtBQUMxQixXQUFRQSxRQUFRLFFBQU9BLElBQVAseUNBQU9BLElBQVAsT0FBZ0IsUUFBeEIsSUFBb0MsQ0FBQ0MsTUFBTUMsT0FBTixDQUFjRixJQUFkLENBQTdDO0FBQ0giLCJmaWxlIjoiMS5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBmdW5jdGlvbiBpc09iamVjdChpdGVtKXtcclxuICAgIHJldHVybiAoaXRlbSAmJiB0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoaXRlbSkpO1xyXG59XG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL2lzT2JqZWN0LmpzIl0sInNvdXJjZVJvb3QiOiIifQ=="); + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + + eval("\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.isArray = isArray;\nfunction isArray(item) {\n return item && Array.isArray(item);\n}\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvaXNBcnJheS5qcz9lNjdmIl0sIm5hbWVzIjpbImlzQXJyYXkiLCJpdGVtIiwiQXJyYXkiXSwibWFwcGluZ3MiOiI7Ozs7O1FBQWdCQSxPLEdBQUFBLE87QUFBVCxTQUFTQSxPQUFULENBQWlCQyxJQUFqQixFQUFzQjtBQUN6QixXQUFRQSxRQUFRQyxNQUFNRixPQUFOLENBQWNDLElBQWQsQ0FBaEI7QUFDSCIsImZpbGUiOiIyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIGlzQXJyYXkoaXRlbSl7XHJcbiAgICByZXR1cm4gKGl0ZW0gJiYgQXJyYXkuaXNBcnJheShpdGVtKSk7XHJcbn1cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvaXNBcnJheS5qcyJdLCJzb3VyY2VSb290IjoiIn0="); + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/package.json b/package.json index 2637357..984b416 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,10 @@ { "name": "nested-object-assign", - "version": "1.0.1", + "version": "1.0.2", "description": "Package to support nested merging of objects & properties, using Object.Assign", "main": "./index.js", "scripts": { + "start": "npm run-script build-dev", "prepublish": "npm run build-all", "preversion": "npm run build-all && npm run unit", "version": "git add .", diff --git a/src/isArray.js b/src/isArray.js new file mode 100644 index 0000000..ade9994 --- /dev/null +++ b/src/isArray.js @@ -0,0 +1,3 @@ +export function isArray(item){ + return (item && Array.isArray(item)); +} \ No newline at end of file diff --git a/src/nestedObjectAssign.js b/src/nestedObjectAssign.js index e3986d0..2358fab 100644 --- a/src/nestedObjectAssign.js +++ b/src/nestedObjectAssign.js @@ -1,4 +1,5 @@ -import {isObject} from './isObject'; +import { isObject } from './isObject'; +import { isArray } from './isArray'; export default function nestedObjectAssign(target, ...sources){ if (!sources.length) @@ -9,12 +10,18 @@ export default function nestedObjectAssign(target, ...sources){ if (isObject(target) && isObject(source)){ for (const key in source){ if (isObject(source[key])){ - if (!target[key]) + if (!target[key]) { Object.assign(target, {[key]: {}}); + } nestedObjectAssign(target[key], source[key]); - } - else { + } else if (isArray(source[key])) { + if (!target[key]) { + Object.assign(target, {[key]: []}); + } + + target[key] = target[key].concat(source[key]); + } else { Object.assign(target, {[key]: source[key]}); } } From 3e144cf093f0f5302d610c301bf320ed9b4d7992 Mon Sep 17 00:00:00 2001 From: Eirik Horvath Date: Thu, 21 Dec 2017 15:58:15 +0100 Subject: [PATCH 2/2] Added array to the mock data in test to validate that arrays now concat correctly. --- test/nestedObjectAssign.spec.js | 45 +++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/test/nestedObjectAssign.spec.js b/test/nestedObjectAssign.spec.js index 7347b58..ef9ec8a 100644 --- a/test/nestedObjectAssign.spec.js +++ b/test/nestedObjectAssign.spec.js @@ -1,29 +1,45 @@ import { expect } from 'chai'; import nestedObjectAssign from '../index.js'; -var mockData = { +const mockData = { default: { heading: 'title', body: { paragraph: 'p', heading: 'h1' - } + }, + products: [ + { + paragraph: 'p', + heading: 'h1' + } + ] }, first: { body: { span: 'span', header: 'header' - } + }, + products: [ + { + span: 'span', + header: 'header' + } + ] }, second: { body: { heading2: 'h2' - } + }, + products: [ + { + heading2: 'h2' + } + ] } - }; -var expectedData = { +const expectedData = { heading: 'title', body: { paragraph: 'p', @@ -31,11 +47,24 @@ var expectedData = { span: 'span', header: 'header', heading2: 'h2' - } + }, + products: [ + { + paragraph: 'p', + heading: 'h1' + }, + { + span: 'span', + header: 'header' + }, + { + heading2: 'h2' + } + ] }; describe('Given an instance of nestedObjectAssign', function() { - describe('when i merge the mockData', function() { + describe('when I merge the mockData', function() { it('it should be equal to expectedData', () => { expect(JSON.stringify(nestedObjectAssign({}, mockData.default, mockData.first, mockData.second))).to.be.equal(JSON.stringify(expectedData)); });