@dyihoon90/glogging
Version:
HTTP request logging middleware & transaction function decorator for express, using winston
99 lines • 3.78 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.traverseAndMutateObject = traverseAndMutateObject;
exports.redactProperties = redactProperties;
exports.isPlainObject = isPlainObject;
var lodash_1 = require("lodash");
/**
* Traverse the object deeply, calling callback on all properties that are not object
* Arrays and objects are both considered object
* Removes circular references
* Limits the traversal depth to prevent excessive recursion
* Note: Mutates the obj passed in
* @param obj The object to traverse and mutate
* @param callback Function to call on each non-object property
* @param maxDepth Maximum depth to traverse (default: 100)
* @param currentDepth Current depth of traversal (used internally)
* @param seen Set of already seen objects (used for circular reference detection)
* @returns The mutated object
*/
function traverseAndMutateObject(obj, callback, maxDepth, currentDepth, seen) {
if (maxDepth === void 0) { maxDepth = 5; }
if (currentDepth === void 0) { currentDepth = 0; }
if (seen === void 0) { seen = new Set(); }
if (!obj || typeof obj !== 'object') {
return obj;
}
// If we've reached the maximum depth, stop traversing
if (currentDepth >= maxDepth) {
return {};
}
// If we've seen this object before, it's a circular reference
if (seen.has(obj)) {
return '[Circular]';
}
// Add this object to the set of seen objects
seen.add(obj);
(0, lodash_1.forIn)(obj, function (value, key) {
if (isPlainObject(value)) {
obj[key] = traverseAndMutateObject(value, callback, maxDepth, currentDepth + 1, seen);
}
else {
obj[key] = callback(key, value);
}
});
// Remove this object from the set of seen objects
seen.delete(obj);
return obj;
}
/**
* Remove from obj, all properties list redactedProperties.
* Recursively remove from nested properties as well
* @param redactedProperties
* @param clonedObj
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function redactProperties(redactedProperties, obj) {
var clonedObj = (0, lodash_1.clone)(obj);
if (!redactedProperties || redactProperties.length === 0 || !obj) {
return clonedObj;
}
if (Array.isArray(clonedObj)) {
clonedObj.forEach(function (_value, index) {
if (redactedProperties.includes(index)) {
clonedObj.splice(index, 1);
}
if (typeof clonedObj[index] === 'object') {
clonedObj[index] = redactProperties(redactedProperties, clonedObj[index]);
}
});
}
else {
Object.keys(clonedObj).forEach(function (key) {
if (redactedProperties.includes(key)) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
clonedObj[key] = '[REDACTED]';
}
else if (typeof clonedObj[key] === 'object' && clonedObj[key] !== null) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
clonedObj[key] = redactProperties(redactedProperties, clonedObj[key]);
}
});
}
return clonedObj;
}
/**
* Checks if the given value is a plain object.
* A plain object is an object created by the Object constructor or one with a [[Prototype]] of null.
*
* @param value - The value to check
* @returns True if the value is a plain object, false otherwise
*/
function isPlainObject(value) {
if (typeof value !== 'object' || value === null) {
return false;
}
var prototype = Object.getPrototypeOf(value);
return prototype === null || prototype === Object.prototype;
}
//# sourceMappingURL=ObjUtils.js.map