Skip to content

Instantly share code, notes, and snippets.

@Jeff-Lewis
Created November 12, 2016 23:10
Show Gist options
  • Select an option

  • Save Jeff-Lewis/f8649afa6233ab5f1572b92a6e1fc4d5 to your computer and use it in GitHub Desktop.

Select an option

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.
'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