UNPKG

@connectedcars/logutil

Version:
222 lines (217 loc) 7.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.objectToJson = objectToJson; // https://github.com/microsoft/TypeScript/issues/1897 function objectToJson(jsValue) { let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; const seen = []; const maxStringLength = paramEnvOrDefault(options.maxStringLength, 'JSON_MAX_STRING_LENGTH', 100, intFromEnv); const maxArrayLength = paramEnvOrDefault(options.maxArrayLength, 'JSON_MAX_ARRAY_LENGTH', 10, intFromEnv); const maxObjectSize = paramEnvOrDefault(options.maxObjectSize, 'JSON_MAX_OBJECT_SIZE', 10, intFromEnv); const maxDepth = paramEnvOrDefault(options.maxDepth, 'JSON_MAX_DEPTH', 10, intFromEnv); return _objectToJson(jsValue, seen, maxDepth, { maxStringLength, maxArrayLength, maxObjectSize }); } function intFromEnv(envName) { const value = process.env[envName]; if (value === undefined) { return; } const parsed = parseInt(value); if (isNaN(parsed)) { return; } return parsed; } function paramEnvOrDefault(param, env, defaultValue, convert) { if (param !== undefined) { return param; } const envValue = process.env[env]; if (envValue !== undefined) { const converted = convert(envValue); if (converted !== undefined) { return converted; } } return defaultValue; } function _objectToJson(jsValue, seen, maxDepth, options) { if (maxDepth <= 0) { return `(MaxDepth:strippedOut:${typeof jsValue})`; } switch (typeof jsValue) { case 'undefined': return '(undefined)'; case 'boolean': return jsValue; case 'number': { if (isNaN(jsValue)) { return '(NaN)'; } if (!isFinite(jsValue)) { return '(Infinity)'; } return jsValue; } case 'bigint': return `BigInt(${jsValue === null || jsValue === void 0 ? void 0 : jsValue.toString()})`; case 'string': return ( // escape newlines and truncate to max length jsValue.replace(/\n/g, '\\n').substring(0, options.maxStringLength) + (jsValue.length > options.maxStringLength ? '...(truncated)' : '') ); case 'object': { if (jsValue === null) { return null; } seen.push(jsValue); if (Array.isArray(jsValue)) { if (jsValue.length === 0) { return jsValue; } const values = []; for (const value of jsValue) { if (seen.includes(value)) { values.push('(Circular:StrippedOut)'); } else { if (values.length >= options.maxArrayLength) { values.push('truncated...'); break; } values.push(_objectToJson(value, seen, maxDepth - 1, options)); } } return values; } else if (jsValue instanceof Date) { return `Date(${jsValue.toISOString()})`; } else if (Buffer.isBuffer(jsValue)) { return `Buffer(${jsValue.toString('hex').toUpperCase()})`; } else if (jsValue instanceof Error) { const stack = typeof jsValue.stack === 'string' ? parseStack(jsValue.stack, jsValue.constructor.name) : []; let cause = {}; const _cause = jsValue.cause; if ('cause' in jsValue && _cause !== undefined && isJavaScriptValue(_cause)) { seen.push(jsValue); if (seen.includes(_cause)) { cause = { cause: '(Circular:StrippedOut)' }; } else { cause = { cause: _objectToJson(_cause, seen, maxDepth - 1, options) }; } } let context = {}; if ('context' in jsValue) { const _context = jsValue.context; if (_context !== undefined && isJavaScriptValue(_context)) { context = { context: _objectToJson(_context, seen, maxDepth - 1, options) }; } } return { __constructorName: jsValue.constructor.name, message: jsValue.message, stack, ...cause, ...context }; } else if (jsValue instanceof Map) { const obj = {}; for (const [key, value] of jsValue.entries()) { const jsonKey = _objectToJson(key, seen, maxDepth - 1, options); const stringKey = typeof jsonKey === 'string' ? jsonKey : JSON.stringify(jsonKey); obj[stringKey] = _objectToJson(value, seen, maxDepth - 1, options); } return obj; } else if (jsValue instanceof Set) { const arr = []; seen.push(jsValue); for (const value of jsValue.values()) { arr.push(_objectToJson(value, seen, maxDepth - 1, options)); } return arr; } else if (jsValue instanceof WeakMap || jsValue instanceof WeakSet) { return '(WeakCollection:strippedOut)'; } else if (jsValue instanceof RegExp) { return `RegExp(${jsValue.source})`; } else { const keys = Object.keys(jsValue); if (keys.length === 0) { return jsValue; } const obj = {}; //handle class and add class name, but not for anonymous objects if ('constructor' in jsValue && typeof jsValue.constructor === 'function' && 'name' in jsValue.constructor && jsValue.constructor.name !== 'Object') { obj.__constructorName = jsValue.constructor.name; } for (const key of keys.slice(0, options.maxObjectSize)) { const value = jsValue[key]; if (typeof value === 'undefined') { obj[key] = '(undefined)'; } else { if (seen.includes(value)) { obj[key] = '(Circular:StrippedOut)'; } else { obj[key] = _objectToJson(value, seen, maxDepth - 1, options); } } } if (keys.length > options.maxObjectSize) { obj['truncated...'] = true; } return obj; } } case 'function': return jsValue.toString(); default: { assertUnreachable(jsValue, 'Unknown JavaScript type'); } } } /* istanbul ignore next */ function assertUnreachable(x, message) { throw new Error(`${message}: ${JSON.stringify(x)} type: ${typeof x}`); } // Parse a node stack trace to an array of strings, // fallback to the original stack if the format is unknown function parseStack(stack, className) { let maxDepth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 5; if (!stack.startsWith(`${className}: `)) { return stack; } const stackLines = []; for (const line of stack.split('\n')) { if (line.startsWith(' at ')) { stackLines.push(line.substring(7)); } else if (line.startsWith(`${className}: `)) { // skip } else { return stack; } } return stackLines.slice(0, maxDepth); } function isJavaScriptValue(x) { if (x === null || x === undefined) { return true; } const types = ['boolean', 'number', 'bigint', 'string', 'object']; if (types.includes(typeof x)) { return true; } return false; } //# sourceMappingURL=json.js.map