codekingpro/portable-devtools
114k
1const { serializeError } = require('./error')
2
3const deepMap = (input, handler = v => v, path = ['$'], seen = new Set([input])) => {
4 // this is in an effort to maintain bole's error logging behavior
5 if (path.join('.') === '$' && input instanceof Error) {
6 return deepMap({ err: serializeError(input) }, handler, path, seen)
7 }
8 if (input instanceof Error) {
9 return deepMap(serializeError(input), handler, path, seen)
10 }
11 // allows for non-node js environments, sush as workers
12 if (typeof Buffer !== 'undefined' && input instanceof Buffer) {
13 return `[unable to log instanceof buffer]`
14 }
15 if (input instanceof Uint8Array) {
16 return `[unable to log instanceof Uint8Array]`
17 }
18
19 if (Array.isArray(input)) {
20 const result = []
21 for (let i = 0; i < input.length; i++) {
22 const element = input[i]
23 const elementPath = [...path, i]
24 if (element instanceof Object) {
25 if (!seen.has(element)) { // avoid getting stuck in circular reference
26 seen.add(element)
27 result.push(deepMap(handler(element, elementPath), handler, elementPath, seen))
28 }
29 } else {
30 result.push(handler(element, elementPath))
31 }
32 }
33 return result
34 }
35
36 if (input === null) {
37 return null
38 } else if (typeof input === 'object' || typeof input === 'function') {
39 const result = {}
40
41 for (const propertyName of Object.getOwnPropertyNames(input)) {
42 // skip logging internal properties
43 if (propertyName.startsWith('_')) {
44 continue
45 }
46
47 try {
48 const property = input[propertyName]
49 const propertyPath = [...path, propertyName]
50 if (property instanceof Object) {
51 if (!seen.has(property)) { // avoid getting stuck in circular reference
52 seen.add(property)
53 result[propertyName] = deepMap(
54 handler(property, propertyPath), handler, propertyPath, seen
55 )
56 }
57 } else {
58 result[propertyName] = handler(property, propertyPath)
59 }
60 } catch (err) {
61 // a getter may throw an error
62 result[propertyName] = `[error getting value: ${err.message}]`
63 }
64 }
65 return result
66 }
67
68 return handler(input, path)
69}
70
71module.exports = { deepMap }
72 