UNPKG

2.1 kBPlain TextView Raw
1import { AppError, _isErrorObject } from '@naturalcycles/js-lib'
2import { inspect, InspectOptions } from 'util'
3
4export interface InspectAnyOptions extends InspectOptions {
5 /**
6 * @default 10_000
7 */
8 maxLen?: number
9
10 /**
11 * @default false
12 * Set to true to not print Error.stack (keeping just Error.message).
13 */
14 noErrorStack?: boolean
15}
16
17/**
18 * Transforms ANY to human-readable string (via util.inspect mainly).
19 * Safe (no error throwing).
20 *
21 * Correclty prints Errors, AppErrors, ErrorObjects: error.message + \n + inspect(error.data)
22 *
23 * Enforces max length (default to 10_000, pass 0 to skip it).
24 *
25 * Logs numbers as-is, e.g: `6`.
26 * Logs strings as-is (without single quotes around, unlike default util.inspect behavior).
27 * Otherwise - just uses util.inspect() with reasonable defaults.
28 *
29 * Returns 'empty_string' if empty string is passed.
30 * Returns 'undefined' if undefined is passed (default util.inspect behavior).
31 */
32export function inspectAny(obj: any, opt: InspectAnyOptions = {}): string {
33 let s: string
34
35 if (obj instanceof Error) {
36 // Stack includes message
37 s = (!opt.noErrorStack && obj.stack) || [obj?.name, obj.message].filter(Boolean).join(': ')
38
39 if (obj instanceof AppError) {
40 s = [s, Object.keys(obj.data).length > 0 && inspectAny(obj.data, opt)]
41 .filter(Boolean)
42 .join('\n')
43 } else if (typeof (obj as any).code === 'string') {
44 s = (obj as any).code + '\n' + s
45 }
46 } else if (_isErrorObject(obj)) {
47 s = [obj.message, Object.keys(obj.data).length > 0 && inspectAny(obj.data, opt)]
48 .filter(Boolean)
49 .join('\n')
50 } else if (typeof obj === 'string') {
51 s = obj.trim() || 'empty_string'
52 } else {
53 s = inspect(obj, {
54 breakLength: 80, // default: ??
55 depth: 6, // default: 2
56 ...opt,
57 })
58 }
59
60 // todo: think about maybe removing it in favor of maxStringLength/maxArrayLength built-in options
61 // Handle maxLen
62 if (opt.maxLen && s.length > opt.maxLen) {
63 s = s.slice(0, opt.maxLen) + `... ${Math.ceil(s.length / 1024)} KB message truncated`
64 }
65
66 return s
67}