├── .eslintignore ├── .eslintrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── monkey-patch.js ├── package-lock.json ├── package.json └── tests ├── fake.json └── index.test.js /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules/** 2 | node_modules/** 3 | **/vendors/** -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 6 4 | }, 5 | "env": { 6 | "browser": true, 7 | "node": true, 8 | "mocha": true 9 | }, 10 | "rules": { 11 | "arrow-spacing": [2, { "before": true, "after": true }], 12 | "constructor-super":2, 13 | "generator-star-spacing": [2, {"before": false, "after": true}], 14 | "no-class-assign": 2, 15 | "no-const-assign": 2, 16 | "no-dupe-class-members": 2, 17 | "no-this-before-super": 2, 18 | "no-useless-constructor": 2, 19 | "object-shorthand": 2, 20 | "prefer-arrow-callback": 2, 21 | "prefer-const": 2, 22 | "prefer-rest-params": 2, 23 | "prefer-spread": 2, 24 | "prefer-template": 2, 25 | "require-yield": 2, 26 | "template-curly-spacing": [2, "never"], 27 | 28 | "array-bracket-spacing": [2, "never"], 29 | "block-spacing": [2, "always"], 30 | "brace-style": [2, "1tbs"], 31 | "comma-spacing": [2, {"before": false, "after": true}], 32 | "comma-style": [2, "last"], 33 | "computed-property-spacing": [2, "never"], 34 | "consistent-this": [2, "self"], 35 | "eol-last": 2, 36 | "indent": [2, 2, {"SwitchCase": 1}], 37 | "key-spacing": [2, {"beforeColon": false, "afterColon": true}], 38 | "keyword-spacing": [2, {"before": true, "after": true}], 39 | "linebreak-style": [2, "unix"], 40 | "lines-around-comment": [2, { "beforeBlockComment": true, "beforeLineComment": false }], 41 | "max-depth": [2, 4], 42 | "max-nested-callbacks": [2, 2], 43 | "max-params": [2, 4], 44 | "new-cap": 2, 45 | "new-parens": 2, 46 | "no-array-constructor": 2, 47 | "no-mixed-spaces-and-tabs": 2, 48 | "no-multiple-empty-lines": [2, {"max": 1}], 49 | "no-nested-ternary": 2, 50 | "no-new-object": 2, 51 | "no-whitespace-before-property": 2, 52 | "no-spaced-func": 2, 53 | "no-trailing-spaces": 2, 54 | "no-underscore-dangle": [2, { "allowAfterThis": true, "allow": ["_id", "_created"] }], 55 | "no-unneeded-ternary": 2, 56 | "object-curly-spacing": [2, "never"], 57 | "one-var": [2, { 58 | "uninitialized": "always", 59 | "initialized": "never" 60 | }], 61 | "operator-assignment": [2, "always"], 62 | "operator-linebreak": [2, "after"], 63 | "quote-props": [2, "as-needed"], 64 | "quotes": [2, "single"], 65 | "require-jsdoc": 2, 66 | "semi-spacing": [2, {"before": false, "after": true}], 67 | "semi": 2, 68 | "space-before-blocks": 2, 69 | "space-before-function-paren": [2, "never"], 70 | "space-in-parens": [2, "never"], 71 | "space-infix-ops": 2, 72 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 73 | "spaced-comment": [2, "always"], 74 | 75 | "handle-callback-err": 2, 76 | "no-mixed-requires": [1, true], 77 | "no-new-require": 2, 78 | "no-path-concat": 2, 79 | "no-sync": 2, 80 | 81 | "strict": [2, "global"], 82 | 83 | "complexity": [2, 10], 84 | "consistent-return": 2, 85 | "curly": [2, "all"], 86 | "dot-location": [2, "property"], 87 | "dot-notation": [2, {"allowKeywords": true}], 88 | "eqeqeq": 2, 89 | "guard-for-in": 2, 90 | "no-alert": 2, 91 | "no-caller": 2, 92 | "no-else-return": 2, 93 | "no-eq-null": 2, 94 | "no-eval": 2, 95 | "no-extend-native": 2, 96 | "no-extra-bind": 2, 97 | "no-implicit-coercion": 2, 98 | "no-implicit-globals": 2, 99 | "no-implied-eval": 2, 100 | "no-invalid-this": 2, 101 | "no-iterator": 2, 102 | "no-labels": 2, 103 | "no-lone-blocks": 2, 104 | "no-loop-func": 2, 105 | "no-multi-spaces": 2, 106 | "no-multi-str": 2, 107 | "no-native-reassign": 2, 108 | "no-new-func": 2, 109 | "no-new-wrappers": 2, 110 | "no-new": 2, 111 | "no-process-env": 2, 112 | "no-proto": 2, 113 | "no-redeclare": 2, 114 | "no-return-assign": 2, 115 | "no-self-assign": 2, 116 | "no-self-compare": 2, 117 | "no-sequences": 2, 118 | "no-throw-literal": 2, 119 | "no-unmodified-loop-condition": 2, 120 | "no-unused-expressions": 2, 121 | "no-useless-call": 2, 122 | "no-useless-concat": 2, 123 | "no-void": 2, 124 | "no-with": 2, 125 | "radix": [2, "always"], 126 | "wrap-iife": [2, "outside"], 127 | "yoda": [2, "never"], 128 | 129 | "comma-dangle": [2, "never"], 130 | "no-cond-assign": 2, 131 | "no-console": 2, 132 | "no-constant-condition": 2, 133 | "no-debugger": 2, 134 | "no-dupe-args": 2, 135 | "no-dupe-keys": 2, 136 | "no-duplicate-case": 2, 137 | "no-empty-character-class": 2, 138 | "no-empty": 2, 139 | "no-ex-assign": 2, 140 | "no-extra-boolean-cast": 2, 141 | "no-extra-semi": 2, 142 | "no-func-assign": 2, 143 | "no-inner-declarations": 2, 144 | "no-invalid-regexp": 2, 145 | "no-irregular-whitespace": 2, 146 | "no-negated-in-lhs": 2, 147 | "no-obj-calls": 2, 148 | "no-sparse-arrays": 2, 149 | "no-unexpected-multiline": 2, 150 | "no-unreachable": 2, 151 | "use-isnan": 2, 152 | "valid-typeof": 2 153 | } 154 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | notifications: 2 | webhooks: 3 | on_success: always # options: [always|never|change] default: always 4 | on_failure: always # options: [always|never|change] default: always 5 | on_start: true # default: false 6 | language: node_js 7 | sudo: false 8 | node_js: 9 | - "4" 10 | - "5" 11 | - "6" 12 | - "7" 13 | - "8" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Maksim 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | mapper 2 | ====== 3 | 4 | [![Travis CI](https://travis-ci.org/chetverikov/mapperjs.svg?branch=master)](https://travis-ci.org/chetverikov/mapperjs) 5 | [![Join the chat at https://gitter.im/chetverikov/mapperjs](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/chetverikov/mapperjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | 7 | NodeJS Data Mapper for transfer data from old format to new. 8 | 9 | # Install 10 | 11 | ``` 12 | 13 | npm install mapperjs; 14 | 15 | ``` 16 | 17 | # Usage 18 | 19 | ```javascript 20 | 21 | const Mapper = require('mapperjs'); 22 | 23 | mapper = new Mapper( map, options ); 24 | mapper.transfer( source, destination ) 25 | .then(dst_res_obj => { 26 | // call after 27 | } 28 | .catch(err => { 29 | // call after if reject with err 30 | }); 31 | 32 | ``` 33 | 34 | # Map 35 | 36 | The map must be a binary array consisting of the string/array/functions. The first array element should be a string or an array of strings path to data of the original object. 37 | 38 | ```javascript 39 | 40 | // Source data 41 | source = { 42 | title: '', 43 | descriptions: { 44 | short: '', 45 | long: '' 46 | }, 47 | photos: [ 48 | '1.jpg', 49 | '2.jpg', 50 | '3.jpg' 51 | ], 52 | old_photos: [ 53 | 'a.png', 54 | 'b.png' 55 | ] 56 | } 57 | 58 | destination = {}; 59 | 60 | map = { 61 | title: 'title', 62 | /* 63 | * in destination object will be field description with data from descriptions.long 64 | */ 65 | 'descriptions.long': 'description', 66 | /* 67 | * in preview will be first photo from photos 68 | */ 69 | 'photos.0': 'preview' 70 | } 71 | 72 | ``` 73 | 74 | # Sync and Async Map functions 75 | 76 | On the map are the functions for processing the data sync and async. 77 | 78 | ```javascript 79 | 80 | map = { 81 | 82 | /** 83 | * Async map func 84 | * value - content entity id 85 | */ 86 | entityId: function( value ){ 87 | // this.dst - destination 88 | // this.src - source 89 | 90 | retun db.queryById( value ) 91 | .then( entity ){ 92 | 93 | /** 94 | * first arg - error 95 | * second arg - object: 96 | * key - path to destination object 97 | * value - value 98 | 99 | * The second argument may contain multiple key/value to setup more fields and values. 100 | */ 101 | return { entity: entity }; 102 | }) 103 | .catch(err => defer.reject(err)); 104 | }, 105 | 106 | /** 107 | * Sync map func 108 | */ 109 | comments: comments => { 110 | return { comments_count: getCountOnlyActiveComments(comments) }; 111 | } 112 | } 113 | 114 | ``` 115 | 116 | # Debug 117 | 118 | Mapperjs uses the [debug](https://github.com/visionmedia/debug) module internally to log information about route matches and application mode. To see this information, simply set the DEBUG environment variable to substance:* when launching your app and the debug information will appear on the console. 119 | 120 | ```javascript 121 | 122 | DEBUG=mapper* node app.js 123 | 124 | ``` 125 | 126 | # Options 127 | 128 | ## skipError 129 | 130 | For skip error from async callback. Default: false 131 | 132 | > if set to false, then the transfer process will stop after the first error 133 | 134 | ```javascript 135 | 136 | const Mapper = require('mapper'); 137 | 138 | mapper = new Mapper( map, { skipError: true } ); 139 | 140 | // not passed errors in an asynchronous callback, and do not stop the transfer process 141 | mapper.transfer( source, destination ).then(dst_res_obj => { 142 | // call after 143 | }); 144 | 145 | ``` 146 | 147 | ## skipFields 148 | 149 | For skip not required fields, you can use the option skipFields: 150 | 151 | ```javascript 152 | 153 | const Mapper = require('mapper'); 154 | 155 | mapper = new Mapper( map, { skipFields: 'field1 field2 iAnotherField' } ); 156 | 157 | // without fields field1, field2, iAnotherField 158 | mapper.transfer( source, destination ).then(dst_res_obj => { 159 | // call after 160 | }); 161 | 162 | ``` 163 | 164 | 165 | # Example 166 | 167 | ```javascript 168 | 169 | const oldObj = { 170 | username: 'Maksim Chetverikov', 171 | avatar: '2fge0923df08r.jpg', 172 | country: 'Russia' 173 | city: 'Irkutsk' 174 | } 175 | , newObj = { 176 | firstname: '', 177 | lastname: '', 178 | avatar: '', 179 | address: '' 180 | }; 181 | 182 | const map = { 183 | username: username => { 184 | const parts = username.split(' '); 185 | 186 | return { firstname: parts[0], lastname: parts[1] }; 187 | }, 188 | avatar: 'avatar', 189 | 'country city', values => { 190 | return {address: value.country + ', ' + value.city} 191 | } 192 | }; 193 | 194 | const mapper = new Mapper( map ); 195 | 196 | mapper.transfer( oldObj, newObj ).then(obj => console.log( obj )); 197 | 198 | ``` 199 | 200 | results 201 | 202 | ```javascript 203 | 204 | { 205 | firstname: 'Maksim', 206 | lastname: 'Chetverikov', 207 | avatar: '2fge0923df08r.jpg', 208 | address: 'Russia, Irkutsk' 209 | } 210 | 211 | ``` 212 | 213 | # Tests 214 | 215 | ` npm test ` 216 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('./monkey-patch'); 4 | 5 | const mpath = require('mpath'); 6 | const debug = require('debug')('mapper'); 7 | 8 | 9 | /** 10 | * mapper 11 | * 12 | * #### Example 13 | * 14 | * const oldObj = { 15 | * username: 'Maksim Chetverikov', 16 | * avatar: '2fge0923df08r.jpg', 17 | * country: 'Russia' 18 | * city: 'Irkutsk' 19 | * } 20 | * const newObj = { 21 | * firstname: '', 22 | * lastname: '', 23 | * avatar: '', 24 | * address: '' 25 | * }; 26 | * 27 | * const map = [ 28 | * username: function( value ){ 29 | * const parts = username.split(' '); 30 | * 31 | * return {firstname: parts[0], lastname: parts[1]}; 32 | * }, 33 | * avatar: 'avatar', 34 | * 'country city': function( value ){ 35 | * return {'address': value.country + ', ' + value.city} 36 | * } 37 | * ]; 38 | * 39 | * const mapper = new Mapper( map ); 40 | * 41 | * mapper.transfer( oldObj, newObj, function( err, obj ){ 42 | * console.log( obj ); 43 | * }); 44 | * 45 | * 46 | * 47 | * @param map 48 | * @param options 49 | * @returns {Mapper} 50 | * @constructor 51 | */ 52 | class Mapper { 53 | constructor(map, options) { 54 | if (!map || typeof map !== 'object') { 55 | throw new TypeError('Map is not object'); 56 | } 57 | 58 | if (!options) { 59 | options = {}; 60 | } 61 | 62 | this._map = map; 63 | this._keys = Object.keys(this._map) || []; 64 | 65 | if (!this._keys) { 66 | throw new TypeError('Map is empty'); 67 | } 68 | 69 | this.options = Object.assign({}, { 70 | skipError: false, 71 | skipFields: '', 72 | delimiter: ' ' 73 | }, options); 74 | } 75 | 76 | /** 77 | * Set value to destination object 78 | * 79 | * @param map 80 | * @param dstObj 81 | */ 82 | setValue(map, dstObj) { 83 | if (map !== undefined) { 84 | Object.keys(map).forEach(where => { 85 | const what = map[where]; 86 | if (what !== undefined) { 87 | mpath.set(where, what, dstObj); 88 | } 89 | }); 90 | } 91 | } 92 | 93 | /** 94 | * Get value from source object 95 | * 96 | * @param path 97 | * @param obj 98 | * @returns {*} 99 | */ 100 | getValue(path, obj) { 101 | if (path) { 102 | return mpath.get(path, obj); 103 | } 104 | 105 | return undefined; 106 | } 107 | 108 | /** 109 | * 110 | * @param {String} source_path 111 | * @returns {*} 112 | */ 113 | extractor(source_path) { 114 | const paths = source_path.split(this.options.delimiter); 115 | const len = paths.length; 116 | let value, key; 117 | let i = 0; 118 | 119 | debug('Initiated the transfer from %s', paths); 120 | 121 | if (len > 1) { 122 | value = {}; 123 | 124 | while (i < len) { 125 | key = paths[i++]; 126 | value[key] = this.getValue(key, this._src); 127 | } 128 | } else { 129 | value = this.getValue(source_path, this._src); 130 | } 131 | 132 | return value; 133 | } 134 | 135 | /** 136 | * 137 | * @param value 138 | * @returns {Object} 139 | */ 140 | bridge(value) { 141 | const obj = {}; 142 | 143 | obj[this.handler] = value; 144 | 145 | return obj; 146 | } 147 | 148 | /** 149 | * 150 | * @param {Object} map { where: what } 151 | */ 152 | injector(map) { 153 | if (Boolean(map) && typeof map === 'object') { 154 | this.setValue(map, this._dst); 155 | } 156 | } 157 | 158 | /** 159 | * 160 | * @param value 161 | * @param {String|Function} handler 162 | * @returns {Promise} 163 | */ 164 | executor(value, handler) { 165 | const context = {src: this._src, dst: this._dst, handler}; 166 | 167 | if (value != null) { 168 | const func = (typeof handler === 'function') ? handler : this.bridge; 169 | 170 | return new Promise(resolve => resolve(func.call(context, value))) 171 | .then(result => this.injector(result)) 172 | .catch(reason => { 173 | if (!this.options.skipError) { 174 | throw reason; 175 | } 176 | }); 177 | } 178 | } 179 | 180 | /** 181 | * 182 | * @param {Promise} promise 183 | * @param {String|Function} handler 184 | * @param {String} source_path 185 | * @returns {Promise} 186 | */ 187 | reduceHandler(promise, handler, source_path) { 188 | const skipFields = this.options.skipFields; 189 | const delimiter = this.options.delimiter; 190 | let paths = source_path.split(delimiter); 191 | 192 | paths = paths.filter(path => skipFields.indexOf(path) === -1); 193 | 194 | if (!paths.length) { 195 | return promise; 196 | } 197 | 198 | return promise 199 | .then(() => this.extractor(paths.join(delimiter))) 200 | .then(value => this.executor(value, handler)); 201 | } 202 | 203 | /** 204 | * The transfer of data 205 | * from the source object to 206 | * the destination object using 207 | * the map is set in the constructor. 208 | * 209 | * @param src 210 | * @param dst 211 | * @returns {*} 212 | */ 213 | transfer(src, dst) { 214 | if (!src || typeof src !== 'object' || !dst || typeof dst !== 'object') { 215 | return Promise.reject(new TypeError('Source or destination is not object')); 216 | } 217 | 218 | this._src = src; 219 | this._dst = dst; 220 | 221 | return Object 222 | .keys(this._map) 223 | .reduce((accumulator, source_path) => this.reduceHandler(accumulator, this._map[source_path], source_path), Promise.resolve()) 224 | .then(() => dst); 225 | } 226 | } 227 | 228 | module.exports = Mapper; 229 | -------------------------------------------------------------------------------- /monkey-patch.js: -------------------------------------------------------------------------------- 1 | const mpath = require('mpath'); 2 | const reg_dollar_exist = /\$/; 3 | const isNum = /^\d+$/; 4 | 5 | // wait https://github.com/aheckmann/mpath/pull/6 6 | function K(v) { 7 | return v; 8 | } 9 | 10 | mpath.set = function(path, val, o, special, map, _copying, workWithArray) { 11 | var lookup; 12 | 13 | if ('function' == typeof special) { 14 | if (special.length < 2) { 15 | map = special; 16 | special = undefined; 17 | } else { 18 | lookup = special; 19 | special = undefined; 20 | } 21 | } 22 | 23 | map || (map = K); 24 | 25 | var parts = 'string' == typeof path 26 | ? path.split('.') 27 | : path; 28 | 29 | if (!Array.isArray(parts)) { 30 | throw new TypeError('Invalid `path`. Must be either string or array'); 31 | } 32 | 33 | if (null == o) return; 34 | 35 | // the existance of $ in a path tells us if the user desires 36 | // the copying of an array instead of setting each value of 37 | // the array to the one by one to matching positions of the 38 | // current array. 39 | var copy = _copying || reg_dollar_exist.test(path) 40 | , obj = o 41 | , part; 42 | 43 | for (var i = 0, len = parts.length - 1; i < len; ++i) { 44 | part = parts[i]; 45 | 46 | if ('$' == part) { 47 | if (i == len - 1) { 48 | break; 49 | } else { 50 | continue; 51 | } 52 | } 53 | 54 | if (Array.isArray(obj) && !isNum.test(part)) { 55 | var paths = parts.slice(i); 56 | 57 | workWithArray = true; 58 | 59 | if (!copy && Array.isArray(val)) { 60 | for (var j = 0; j < obj.length && j < val.length; ++j) { 61 | // assignment of single values of array 62 | exports.set(paths, val[j], obj[j], special || lookup, map, copy); 63 | } 64 | } else { 65 | for (var j = 0; j < obj.length; ++j) { 66 | // assignment of entire value 67 | exports.set(paths, val, obj[j], special || lookup, map, copy); 68 | } 69 | } 70 | return; 71 | } 72 | 73 | if (!obj[part]) { 74 | if (parts[i + 1] && parts[i + 1] == '$' && !parts[i + 2]) { 75 | obj[part] = []; 76 | } 77 | 78 | if (!workWithArray && parts[i + 1] != '$') { 79 | obj[part] = {}; 80 | } 81 | } 82 | 83 | if (lookup) { 84 | obj = lookup(obj, part); 85 | } else { 86 | obj = special && obj[special] 87 | ? obj[special][part] 88 | : obj[part]; 89 | } 90 | 91 | if (!obj) return; 92 | } 93 | 94 | // process the last property of the path 95 | part = parts[len]; 96 | 97 | // use the special property if exists 98 | if (special && obj[special]) { 99 | obj = obj[special]; 100 | } 101 | 102 | // set the value on the last branch 103 | if (Array.isArray(obj) && !isNum.test(part)) { 104 | if (!copy && Array.isArray(val)) { 105 | for (var item, j = 0; j < obj.length && j < val.length; ++j) { 106 | item = obj[j]; 107 | if (item) { 108 | if (lookup) { 109 | lookup(item, part, map(val[j])); 110 | } else { 111 | if (item[special]) item = item[special]; 112 | item[part] = map(val[j]); 113 | } 114 | } 115 | } 116 | // push element in array 117 | } else if (Array.isArray(obj) && part == '$') { 118 | obj.push(map(val)); 119 | } else { 120 | for (var j = 0; j < obj.length; ++j) { 121 | item = obj[j]; 122 | if (item) { 123 | if (lookup) { 124 | lookup(item, part, map(val)); 125 | } else { 126 | if (item[special]) item = item[special]; 127 | item[part] = map(val); 128 | } 129 | } 130 | } 131 | } 132 | } else { 133 | if (lookup) { 134 | lookup(obj, part, map(val)); 135 | } else { 136 | obj[part] = map(val); 137 | } 138 | } 139 | }; -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mapperjs", 3 | "version": "3.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "balanced-match": { 8 | "version": "1.0.0", 9 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 10 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 11 | "dev": true 12 | }, 13 | "brace-expansion": { 14 | "version": "1.1.8", 15 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 16 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 17 | "dev": true, 18 | "requires": { 19 | "balanced-match": "1.0.0", 20 | "concat-map": "0.0.1" 21 | } 22 | }, 23 | "browser-stdout": { 24 | "version": "1.3.0", 25 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", 26 | "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", 27 | "dev": true 28 | }, 29 | "commander": { 30 | "version": "2.9.0", 31 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 32 | "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", 33 | "dev": true, 34 | "requires": { 35 | "graceful-readlink": "1.0.1" 36 | } 37 | }, 38 | "concat-map": { 39 | "version": "0.0.1", 40 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 41 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 42 | "dev": true 43 | }, 44 | "debug": { 45 | "version": "3.0.1", 46 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.0.1.tgz", 47 | "integrity": "sha512-6nVc6S36qbt/mutyt+UGMnawAMrPDZUPQjRZI3FS9tCtDRhvxJbK79unYBLPi+z5SLXQ3ftoVBFCblQtNSls8w==", 48 | "requires": { 49 | "ms": "2.0.0" 50 | } 51 | }, 52 | "diff": { 53 | "version": "3.2.0", 54 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", 55 | "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", 56 | "dev": true 57 | }, 58 | "escape-string-regexp": { 59 | "version": "1.0.5", 60 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 61 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 62 | "dev": true 63 | }, 64 | "fs.realpath": { 65 | "version": "1.0.0", 66 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 67 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 68 | "dev": true 69 | }, 70 | "glob": { 71 | "version": "7.1.1", 72 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", 73 | "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", 74 | "dev": true, 75 | "requires": { 76 | "fs.realpath": "1.0.0", 77 | "inflight": "1.0.6", 78 | "inherits": "2.0.3", 79 | "minimatch": "3.0.4", 80 | "once": "1.4.0", 81 | "path-is-absolute": "1.0.1" 82 | } 83 | }, 84 | "graceful-readlink": { 85 | "version": "1.0.1", 86 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 87 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", 88 | "dev": true 89 | }, 90 | "growl": { 91 | "version": "1.9.2", 92 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 93 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 94 | "dev": true 95 | }, 96 | "has-flag": { 97 | "version": "1.0.0", 98 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", 99 | "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", 100 | "dev": true 101 | }, 102 | "he": { 103 | "version": "1.1.1", 104 | "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", 105 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", 106 | "dev": true 107 | }, 108 | "inflight": { 109 | "version": "1.0.6", 110 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 111 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 112 | "dev": true, 113 | "requires": { 114 | "once": "1.4.0", 115 | "wrappy": "1.0.2" 116 | } 117 | }, 118 | "inherits": { 119 | "version": "2.0.3", 120 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 121 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 122 | "dev": true 123 | }, 124 | "json3": { 125 | "version": "3.3.2", 126 | "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", 127 | "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", 128 | "dev": true 129 | }, 130 | "lodash._baseassign": { 131 | "version": "3.2.0", 132 | "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", 133 | "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", 134 | "dev": true, 135 | "requires": { 136 | "lodash._basecopy": "3.0.1", 137 | "lodash.keys": "3.1.2" 138 | } 139 | }, 140 | "lodash._basecopy": { 141 | "version": "3.0.1", 142 | "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", 143 | "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", 144 | "dev": true 145 | }, 146 | "lodash._basecreate": { 147 | "version": "3.0.3", 148 | "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", 149 | "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", 150 | "dev": true 151 | }, 152 | "lodash._getnative": { 153 | "version": "3.9.1", 154 | "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", 155 | "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", 156 | "dev": true 157 | }, 158 | "lodash._isiterateecall": { 159 | "version": "3.0.9", 160 | "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", 161 | "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", 162 | "dev": true 163 | }, 164 | "lodash.create": { 165 | "version": "3.1.1", 166 | "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", 167 | "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", 168 | "dev": true, 169 | "requires": { 170 | "lodash._baseassign": "3.2.0", 171 | "lodash._basecreate": "3.0.3", 172 | "lodash._isiterateecall": "3.0.9" 173 | } 174 | }, 175 | "lodash.defaults": { 176 | "version": "4.2.0", 177 | "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", 178 | "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" 179 | }, 180 | "lodash.isarguments": { 181 | "version": "3.1.0", 182 | "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", 183 | "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", 184 | "dev": true 185 | }, 186 | "lodash.isarray": { 187 | "version": "3.0.4", 188 | "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", 189 | "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", 190 | "dev": true 191 | }, 192 | "lodash.isfunction": { 193 | "version": "3.0.8", 194 | "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.8.tgz", 195 | "integrity": "sha1-TbcJ/IG8So/XEnpFilNGxc3OLGs=" 196 | }, 197 | "lodash.isobject": { 198 | "version": "3.0.2", 199 | "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", 200 | "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=" 201 | }, 202 | "lodash.keys": { 203 | "version": "3.1.2", 204 | "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", 205 | "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", 206 | "dev": true, 207 | "requires": { 208 | "lodash._getnative": "3.9.1", 209 | "lodash.isarguments": "3.1.0", 210 | "lodash.isarray": "3.0.4" 211 | } 212 | }, 213 | "minimatch": { 214 | "version": "3.0.4", 215 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 216 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 217 | "dev": true, 218 | "requires": { 219 | "brace-expansion": "1.1.8" 220 | } 221 | }, 222 | "minimist": { 223 | "version": "0.0.8", 224 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 225 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 226 | "dev": true 227 | }, 228 | "mkdirp": { 229 | "version": "0.5.1", 230 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 231 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 232 | "dev": true, 233 | "requires": { 234 | "minimist": "0.0.8" 235 | } 236 | }, 237 | "mocha": { 238 | "version": "3.5.3", 239 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", 240 | "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", 241 | "dev": true, 242 | "requires": { 243 | "browser-stdout": "1.3.0", 244 | "commander": "2.9.0", 245 | "debug": "2.6.8", 246 | "diff": "3.2.0", 247 | "escape-string-regexp": "1.0.5", 248 | "glob": "7.1.1", 249 | "growl": "1.9.2", 250 | "he": "1.1.1", 251 | "json3": "3.3.2", 252 | "lodash.create": "3.1.1", 253 | "mkdirp": "0.5.1", 254 | "supports-color": "3.1.2" 255 | }, 256 | "dependencies": { 257 | "debug": { 258 | "version": "2.6.8", 259 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", 260 | "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", 261 | "dev": true, 262 | "requires": { 263 | "ms": "2.0.0" 264 | } 265 | } 266 | } 267 | }, 268 | "mpath": { 269 | "version": "0.3.0", 270 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.3.0.tgz", 271 | "integrity": "sha1-elj3iem1/TyUUgY0FXlg8mvV70Q=" 272 | }, 273 | "ms": { 274 | "version": "2.0.0", 275 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 276 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 277 | }, 278 | "once": { 279 | "version": "1.4.0", 280 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 281 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 282 | "dev": true, 283 | "requires": { 284 | "wrappy": "1.0.2" 285 | } 286 | }, 287 | "path-is-absolute": { 288 | "version": "1.0.1", 289 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 290 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 291 | "dev": true 292 | }, 293 | "should": { 294 | "version": "13.0.1", 295 | "resolved": "https://registry.npmjs.org/should/-/should-13.0.1.tgz", 296 | "integrity": "sha512-PyGb++NcZXyHq1lK4Lv9JC2/qjRia1gsE6wrMEOpJX1t7bxEZlY0oYijSq7xgvp6rPJiH8DVvcmw/LWtFaw1vw==", 297 | "dev": true, 298 | "requires": { 299 | "should-equal": "2.0.0", 300 | "should-format": "3.0.3", 301 | "should-type": "1.4.0", 302 | "should-type-adaptors": "1.0.1", 303 | "should-util": "1.0.0" 304 | } 305 | }, 306 | "should-equal": { 307 | "version": "2.0.0", 308 | "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", 309 | "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", 310 | "dev": true, 311 | "requires": { 312 | "should-type": "1.4.0" 313 | } 314 | }, 315 | "should-format": { 316 | "version": "3.0.3", 317 | "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", 318 | "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", 319 | "dev": true, 320 | "requires": { 321 | "should-type": "1.4.0", 322 | "should-type-adaptors": "1.0.1" 323 | } 324 | }, 325 | "should-type": { 326 | "version": "1.4.0", 327 | "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", 328 | "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", 329 | "dev": true 330 | }, 331 | "should-type-adaptors": { 332 | "version": "1.0.1", 333 | "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.0.1.tgz", 334 | "integrity": "sha1-7+VVPN9oz/ZuXF9RtxLcNRx3vqo=", 335 | "dev": true, 336 | "requires": { 337 | "should-type": "1.4.0", 338 | "should-util": "1.0.0" 339 | } 340 | }, 341 | "should-util": { 342 | "version": "1.0.0", 343 | "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz", 344 | "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=", 345 | "dev": true 346 | }, 347 | "supports-color": { 348 | "version": "3.1.2", 349 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", 350 | "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", 351 | "dev": true, 352 | "requires": { 353 | "has-flag": "1.0.0" 354 | } 355 | }, 356 | "wrappy": { 357 | "version": "1.0.2", 358 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 359 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 360 | "dev": true 361 | } 362 | } 363 | } 364 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mapperjs", 3 | "version": "3.0.1", 4 | "description": "The solution for node.js for migrate data from the old format to the new format data with pre-processing", 5 | "keywords": [ 6 | "data", 7 | "mapper", 8 | "map", 9 | "parser", 10 | "object", 11 | "keys", 12 | "helper", 13 | "utility" 14 | ], 15 | "author": "Maksim Chetverikov ", 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/chetverikov/mapper.git" 19 | }, 20 | "dependencies": { 21 | "debug": "^3.0.1", 22 | "mpath": "^0.3.0" 23 | }, 24 | "devDependencies": { 25 | "should": "*", 26 | "mocha": "*" 27 | }, 28 | "main": "index", 29 | "engines": { 30 | "node": ">= 4.x" 31 | }, 32 | "bugs": { 33 | "url": "https://github.com/chetverikov/mapper/issues" 34 | }, 35 | "homepage": "https://github.com/chetverikov/mapper", 36 | "scripts": { 37 | "test": "NODE_ENV=test node_modules/.bin/mocha --async-only tests/**/*.test.js" 38 | }, 39 | "license": "MIT" 40 | } 41 | -------------------------------------------------------------------------------- /tests/fake.json: -------------------------------------------------------------------------------- 1 | { 2 | "field_string": "Foooooo", 3 | "field_array_of_string" : [ 4 | "one", 5 | "two" 6 | ], 7 | "field_array_of_object" : [ 8 | { "a": "b", "c": "d"}, 9 | { "e": "f", "g": "g"} 10 | ], 11 | "field_object": { 12 | "a": { 13 | "b": "c", 14 | "d": [1, 2, 3], 15 | "e": { 16 | "f": "fooo", 17 | "g": "gggg" 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/index.test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * @fileOverview Description file. 5 | * @author Maksim Chetverikov 6 | */ 7 | 8 | const Mapper = require('../'); 9 | const fake = require('./fake.json'); 10 | 11 | require('should'); 12 | 13 | describe('MapperJs', () => { 14 | 15 | it('default', () => { 16 | const dst_obj = {}; 17 | 18 | const mapper = new Mapper({ 19 | field_string: val => { 20 | return {string: val, string_up: val.toUpperCase()}; 21 | }, 22 | 23 | /* eslint object-shorthand: 0 */ 24 | field_array_of_string: function(val) { 25 | const result = [val[0]]; 26 | 27 | result.push(this.dst.string); 28 | 29 | return {array_of_string: result}; 30 | } 31 | }); 32 | 33 | return mapper.transfer(fake, dst_obj).then(dst => { 34 | const result = { 35 | string: 'Foooooo', 36 | string_up: 'FOOOOOO', 37 | array_of_string: ['one', 'Foooooo'] 38 | }; 39 | 40 | dst.should.eql(result); 41 | dst_obj.should.eql(result); 42 | }); 43 | }); 44 | 45 | it('undefined field in src', () => { 46 | const map = new Mapper({ 47 | field_string: 'string', 48 | field_not_exist: 'foo' 49 | }); 50 | 51 | const dst_obj = {}; 52 | 53 | return map.transfer(fake, dst_obj).then(dst => { 54 | const result = { 55 | string: 'Foooooo' 56 | }; 57 | 58 | dst.should.eql(result); 59 | dst_obj.should.eql(result); 60 | }); 61 | }); 62 | 63 | it('undefined field in src with handler', () => { 64 | const map = new Mapper({ 65 | field_string: 'string', 66 | field_not_exist: () => { 67 | return {foo: 'bar'}; 68 | } 69 | }); 70 | 71 | const dst_obj = {}; 72 | 73 | return map.transfer(fake, dst_obj).then(dst => { 74 | const result = { 75 | string: 'Foooooo' 76 | }; 77 | 78 | dst.should.eql(result); 79 | dst_obj.should.eql(result); 80 | }); 81 | }); 82 | 83 | it('get deep field', () => { 84 | const map = new Mapper({ 85 | field_string: 'string', 86 | 'field_object.a.e.f': 'foo' 87 | }); 88 | 89 | const dst_obj = {}; 90 | 91 | return map.transfer(fake, dst_obj).then(dst => { 92 | const result = { 93 | string: 'Foooooo', 94 | foo: 'fooo' 95 | }; 96 | 97 | dst.should.eql(result); 98 | dst_obj.should.eql(result); 99 | }); 100 | }); 101 | 102 | it('get array elem deep field ', () => { 103 | const map = new Mapper({ 104 | field_string: 'string', 105 | 'field_object.a.d.0': 'foo' 106 | }); 107 | 108 | const dst_obj = {}; 109 | 110 | return map.transfer(fake, dst_obj).then(dst => { 111 | const result = { 112 | string: 'Foooooo', 113 | foo: 1 114 | }; 115 | 116 | dst.should.eql(result); 117 | dst_obj.should.eql(result); 118 | }); 119 | }); 120 | 121 | it('create deep field in dst', () => { 122 | const map = new Mapper({ 123 | field_array_of_object: 'i.deep.deep.field' 124 | }); 125 | 126 | const dst_obj = {}; 127 | 128 | return map.transfer(fake, dst_obj).then(dst => { 129 | const result = { 130 | i: { 131 | deep: { 132 | deep: { 133 | field: fake.field_array_of_object 134 | } 135 | } 136 | } 137 | }; 138 | 139 | dst.should.eql(result); 140 | dst_obj.should.eql(result); 141 | }); 142 | }); 143 | 144 | it('create deep field array in dst', () => { 145 | const map = new Mapper({ 146 | 'field_array_of_object.0': 'i.deep.array.$', // create 147 | 'field_array_of_object.1': 'i.deep.array.$' // add 148 | }); 149 | 150 | const dst_obj = {}; 151 | 152 | return map.transfer(fake, dst_obj).then(dst => { 153 | const result = { 154 | i: { 155 | deep: { 156 | array: fake.field_array_of_object 157 | } 158 | } 159 | }; 160 | 161 | dst.should.eql(result); 162 | dst_obj.should.eql(result); 163 | }); 164 | }); 165 | 166 | it('multi field', () => { 167 | const map = new Mapper({ 168 | 'field_object.a.e.f field_string': values => { 169 | return {multi: [values['field_object.a.e.f'], values.field_string].join(' ')}; 170 | } 171 | }); 172 | 173 | const dst_obj = {}; 174 | 175 | return map.transfer(fake, dst_obj).then(dst => { 176 | const result = { 177 | multi: [fake.field_object.a.e.f, fake.field_string].join(' ') 178 | }; 179 | 180 | dst.should.eql(result); 181 | dst_obj.should.eql(result); 182 | }); 183 | }); 184 | 185 | it('Skip options', () => { 186 | const map = new Mapper({ 187 | field_string: 'string', 188 | field_array_of_string: function(val) { 189 | const result = [val[0]]; 190 | 191 | result.push(this.dst.string); 192 | 193 | return {array_of_string: result}; 194 | } 195 | }, {skipFields: 'field_array_of_string'}); 196 | 197 | const dst_obj = {}; 198 | 199 | return map.transfer(fake, dst_obj).then(dst => { 200 | const result = { 201 | string: 'Foooooo' 202 | }; 203 | 204 | dst.should.eql(result); 205 | dst_obj.should.eql(result); 206 | }); 207 | }); 208 | 209 | it('handler return promise', () => { 210 | const map = new Mapper({ 211 | field_string: value => 212 | new Promise(resolve => 213 | setTimeout(() => resolve({string: value}), 50) 214 | ) 215 | }, {skipFields: 'field_array_of_string'}); 216 | 217 | const dst_obj = {}; 218 | 219 | return map.transfer(fake, dst_obj).then(dst => { 220 | const result = { 221 | string: 'Foooooo' 222 | }; 223 | 224 | dst.should.eql(result); 225 | dst_obj.should.eql(result); 226 | }); 227 | }); 228 | 229 | it('handler return rejected promise', () => { 230 | const map = new Mapper({ 231 | field_string: value => 232 | new Promise((resolve, reject) => 233 | setTimeout(() => reject('Not set value'), 50) 234 | ) 235 | }, {skipFields: 'field_array_of_string'}); 236 | 237 | const dst_obj = {}; 238 | 239 | return map.transfer(fake, dst_obj).catch(err => err.should.eql('Not set value')); 240 | }); 241 | 242 | it('handler return rejected promise with skipError option', () => { 243 | const map = new Mapper({ 244 | field_string: value => 245 | new Promise((resolve, reject) => 246 | setTimeout(() => reject('Not set value'), 50) 247 | ) 248 | , 249 | 'field_object.a.b': 'string' 250 | }, {skipError: true}); 251 | 252 | const dst_obj = {}; 253 | 254 | return map.transfer(fake, dst_obj).then(dst => { 255 | const result = { 256 | string: 'c' 257 | }; 258 | 259 | dst.should.eql(result); 260 | dst_obj.should.eql(result); 261 | }); 262 | }); 263 | 264 | it('handler with exception', () => { 265 | const map = new Mapper({ 266 | field_string: () => { 267 | throw new Error('Ho ho ho'); 268 | }, 269 | 'field_object.a.b': 'string' 270 | }, {skipError: true}); 271 | 272 | const dst_obj = {}; 273 | 274 | return map.transfer(fake, dst_obj).then(dst => { 275 | const result = { 276 | string: 'c' 277 | }; 278 | 279 | dst.should.eql(result); 280 | dst_obj.should.eql(result); 281 | }); 282 | }); 283 | }); 284 | --------------------------------------------------------------------------------