Created
November 12, 2016 23:10
-
-
Save Jeff-Lewis/f8649afa6233ab5f1572b92a6e1fc4d5 to your computer and use it in GitHub Desktop.
MongoDB helper for storing logged events and errors with circular or odd field names.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use strict'; | |
| var _ = require('lodash'); | |
| /** | |
| * Prepares metadata to store into database. | |
| * @param {*} obj Metadata | |
| * @return {*} | |
| */ | |
| module.exports.prepareData = function prepareData (obj) { | |
| var clonedObj = cloneDeep(obj); | |
| if (typeof clonedObj === 'object' && clonedObj !== null) { | |
| makeObjectNonCircular(clonedObj); | |
| //cleanFieldNames(clonedObj); | |
| } | |
| return clonedObj; | |
| }; | |
| /** | |
| * | |
| * @param {*} obj | |
| * @returns {*} | |
| */ | |
| function cloneDeep (obj) { | |
| if (_.isUndefined(obj) || _.isNull(obj)) { | |
| return obj; | |
| } | |
| var copy = {}; | |
| // Lodash does not clone Error objects. | |
| if (obj instanceof Error) { | |
| _.forEach(_.keysIn(obj), function (key) { | |
| if (!_.isFunction(obj)) { | |
| var cleanedFieldName = cleanFieldName(key); | |
| copy[cleanedFieldName] = cloneDeep(obj[key]); | |
| } | |
| }); | |
| return copy; | |
| } else if (_.isFunction(obj.toJSON)) { | |
| return obj.toJSON(); | |
| } else if (_.isObjectLike(obj)) { | |
| _.forEach(_.keysIn(obj), function (key) { | |
| if (!_.isFunction(obj)) { | |
| var cleanedFieldName = cleanFieldName(key); | |
| copy[cleanedFieldName] = cloneDeep(obj[key]); | |
| } | |
| }); | |
| return copy; | |
| } else { | |
| return obj; | |
| } | |
| //return _.cloneDeep(obj); | |
| } | |
| /** | |
| * Removes unexpected characters from metadata field names. | |
| * @param {Object} object Object to clean | |
| */ | |
| function cleanFieldNames (object) { | |
| for (var field in object) { | |
| if (object.hasOwnProperty(field)) { | |
| var value = object[field]; | |
| if (field.indexOf('.') !== 0) { | |
| delete object[field]; | |
| field = field.replace('.', '[dot]'); | |
| object[field] = value; | |
| } | |
| if (field.indexOf('$') === 0) { | |
| delete object[field]; | |
| field = field.replace('$', '[$]'); | |
| object[field] = value; | |
| } | |
| //if (typeof value === 'object') { | |
| if (_.isArrayLikeObject(value)) { | |
| cleanFieldNames(value); | |
| } | |
| } | |
| } | |
| } | |
| function cleanFieldName (fieldName) { | |
| var field = fieldName; | |
| if (fieldName.indexOf('.') !== 0) { | |
| field = fieldName.replace('.', '[dot]'); | |
| } | |
| if (field.indexOf('$') === 0) { | |
| field = field.replace('$', '[$]'); | |
| } | |
| return field; | |
| } | |
| /** | |
| * Cleans object from circular references, replaces them with string "[Circular]" | |
| * @param {Object} node Current object or its leaf | |
| * @param {Array=} opt_parents Object's parents | |
| */ | |
| function makeObjectNonCircular (node, opt_parents) { | |
| opt_parents = opt_parents || []; | |
| var keys = Object.keys(node); | |
| var i; | |
| var value; | |
| opt_parents.push(node); // add self to current path | |
| for (i = keys.length - 1; i >= 0; --i) { | |
| value = node[keys[i]]; | |
| if (value && typeof value === 'object') { | |
| if (opt_parents.indexOf(value) === -1) { | |
| // check child nodes | |
| makeObjectNonCircular(value, opt_parents); | |
| } else { | |
| // circularity detected! | |
| node[keys[i]] = '[Circular]'; | |
| } | |
| } else if (value && _.isArray(value)) { | |
| // check child nodes | |
| /* jshint -W083 */ | |
| _.forEach(value, function (valueNode) { | |
| makeObjectNonCircular(valueNode, opt_parents); | |
| }); | |
| } | |
| } | |
| opt_parents.pop(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment