• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taichunmin / chameleon-ultra.js / 15847482271

24 Jun 2025 10:04AM UTC coverage: 69.194% (+5.8%) from 63.351%
15847482271

push

github

web-flow
v0.3.30: change to vitest and lodash-es (#196)

502 of 657 branches covered (76.41%)

Branch coverage included in aggregate %.

12 of 18 new or added lines in 14 files covered. (66.67%)

218 existing lines in 5 files now uncovered.

2683 of 3946 relevant lines covered (67.99%)

3159783.57 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.97
/src/plugin/Debug.ts
1
import { type Buffer } from '@taichunmin/buffer'
2
import createDebugger, { type Debugger } from 'debug'
1✔
3
import * as _ from 'lodash-es'
1✔
4
import { type PluginInstallContext as ChameleonCtx, type ChameleonPlugin } from '../ChameleonUltra'
5
import { setObject } from '../iifeExportHelper'
1✔
6

7
let Buffer1: typeof Buffer
1✔
8

UNCOV
9
export default class Debug implements ChameleonPlugin {
×
10
  debugers = new Map<string, Debugger>()
×
UNCOV
11
  filter?: DebugFilter
×
12
  name = 'debug'
×
13

UNCOV
14
  async install (context: ChameleonCtx): Promise<this> {
×
15
    const { ultra } = context
×
16
    if (_.isNil(Buffer1)) Buffer1 = context.Buffer
×
17
    ultra.emitter.on('error', (err: Error) => {
×
18
      const errJson = errToJson(err)
×
19
      ultra.emitter.emit('debug', 'error', jsonStringify(errJson))
×
20
      console.error(errJson)
×
UNCOV
21
    })
×
22
    ultra.emitter.on('debug', (namespace: string, formatter: any, ...args: [] | any[]) => {
×
23
      if (!(this.filter?.(namespace, formatter, ...args) ?? true)) return
×
24
      const debug = this.debugers.get(namespace) ?? createDebugger(`ultra:${namespace}`)
×
25
      if (!this.debugers.has(namespace)) this.debugers.set(namespace, debug)
×
26
      debug(formatter, ...args)
×
UNCOV
27
    })
×
28
    return this
×
UNCOV
29
  }
×
UNCOV
30
}
×
31

32
setObject(globalThis, ['ChameleonUltraJS', 'Debug'], Debug)
1✔
33

34
type DebugFilter = (namespace: string, formatter: any, ...args: [] | any[]) => boolean
35

36
const ERROR_KEYS = [
1✔
37
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Error
38
  'columnNumber',
1✔
39
  'filename',
1✔
40
  'lineNumber',
1✔
41
  'message',
1✔
42
  'name',
1✔
43
  'stack',
1✔
44

45
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError
46
  'errors',
1✔
47

48
  // https://nodejs.org/api/errors.html
49
  'address',
1✔
50
  'code',
1✔
51
  'dest',
1✔
52
  'errno',
1✔
53
  'function',
1✔
54
  'info',
1✔
55
  'library',
1✔
56
  'opensslErrorStack',
1✔
57
  'path',
1✔
58
  'port',
1✔
59
  'reason',
1✔
60
  'syscall',
1✔
61

62
  // axios: https://github.com/axios/axios/blob/v1.x/lib/core/AxiosError.js
63
  'config',
1✔
64
  'description',
1✔
65
  'fileName',
1✔
66
  'number',
1✔
67
  'request',
1✔
68
  'response.data',
1✔
69
  'response.headers',
1✔
70
  'response.status',
1✔
71
  'status',
1✔
72

73
  // http-errors: https://github.com/jshttp/http-errors/blob/master/index.js
74
  'statusCode',
1✔
75
  'statusMessage',
1✔
76

77
  // GraphQLError: https://www.graphql-js.org/api-v16/error/
78
  'args',
1✔
79
  'originalError',
1✔
80
  'positions',
1✔
81
  'source',
1✔
82
  'locations',
1✔
83
  'line',
1✔
84
  'column',
1✔
85

86
  // custom
87
  'data',
1✔
88
] as const
1✔
89

90
/**
91
 * @group Internal
92
 * @internal
93
 */
94
export function errToJson<T extends Error & { cause?: any, stack?: any }> (err: T): Partial<T> {
1✔
95
  const tmp: any = {
3✔
96
    ..._.pick(err, ERROR_KEYS),
3✔
97
    ...(_.isNil(err.cause) ? {} : { cause: errToJson(err.cause) }),
3✔
98
  }
3✔
99
  return tmp
3✔
100
}
3✔
101

102
/**
103
 * @group Internal
104
 * @internal
105
 */
106
export function stringifyClone (obj: any): any {
1✔
107
  const preventCircular = new Set()
1✔
108
  return _.cloneDeepWith(obj, val1 => {
1✔
109
    if (_.isObject(val1) && !_.isEmpty(val1)) {
15✔
110
      if (preventCircular.has(val1)) return '[Circular]'
6✔
111
      preventCircular.add(val1)
5✔
112
    }
5✔
113
    if (Buffer1?.isBuffer(val1)) return { type: 'Buffer', hex: val1.toString('hex') }
15✔
114
    if (typeof val1 === 'bigint') return val1.toString()
15✔
115
    if (val1 instanceof Error) return errToJson(val1)
15✔
116
    if (val1 instanceof Map) return _.fromPairs([...val1.entries()])
15✔
117
    if (val1 instanceof Set) return [...val1.values()]
15✔
118
    if (val1 instanceof Date) return val1.toISOString()
15✔
119
  })
1✔
120
}
1✔
121

122
/**
123
 * @group Internal
124
 * @internal
125
 */
126
export function stringifyReplacer (this: any, key: any, val: any): any {
1✔
127
  if (key.length > 1 && key[0] === '_') return undefined
20✔
128
  const censored = this?._censored ?? []
20✔
129
  for (const key1 of censored) {
20✔
130
    if (!_.hasIn(this, key1)) continue
2✔
131
    _.set(this, key1, '[Censored]')
1✔
132
  }
1✔
133
  delete this?._censored
19✔
134
  return this[key]
20✔
135
}
20✔
136

137
/**
138
 * @group Internal
139
 * @internal
140
 */
141
export function jsonStringify (obj: object, space?: number): string {
1✔
142
  return JSON.stringify(stringifyClone(obj), stringifyReplacer, space)
1✔
143
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc