UNPKG

3.92 kBJavaScriptView Raw
1'use strict'
2
3const chalk = require('chalk')
4const jmespath = require('jmespath')
5const colors = require('./lib/colors')
6const { ERROR_LIKE_KEYS, MESSAGE_KEY, TIMESTAMP_KEY } = require('./lib/constants')
7const {
8 isObject,
9 prettifyErrorLog,
10 prettifyLevel,
11 prettifyMessage,
12 prettifyMetadata,
13 prettifyObject,
14 prettifyTime
15} = require('./lib/utils')
16
17const bourne = require('@hapi/bourne')
18const jsonParser = input => {
19 try {
20 return { value: bourne.parse(input, { protoAction: 'remove' }) }
21 } catch (err) {
22 return { err }
23 }
24}
25
26const defaultOptions = {
27 colorize: chalk.supportsColor,
28 crlf: false,
29 errorLikeObjectKeys: ERROR_LIKE_KEYS,
30 errorProps: '',
31 levelFirst: false,
32 messageKey: MESSAGE_KEY,
33 messageFormat: false,
34 timestampKey: TIMESTAMP_KEY,
35 translateTime: false,
36 useMetadata: false,
37 outputStream: process.stdout,
38 customPrettifiers: {}
39}
40
41module.exports = function prettyFactory (options) {
42 const opts = Object.assign({}, defaultOptions, options)
43 const EOL = opts.crlf ? '\r\n' : '\n'
44 const IDENT = ' '
45 const messageKey = opts.messageKey
46 const messageFormat = opts.messageFormat
47 const timestampKey = opts.timestampKey
48 const errorLikeObjectKeys = opts.errorLikeObjectKeys
49 const errorProps = opts.errorProps.split(',')
50 const customPrettifiers = opts.customPrettifiers
51 const ignoreKeys = opts.ignore ? new Set(opts.ignore.split(',')) : undefined
52
53 const colorizer = colors(opts.colorize)
54 const search = opts.search
55
56 return pretty
57
58 function pretty (inputData) {
59 let log
60 if (!isObject(inputData)) {
61 const parsed = jsonParser(inputData)
62 if (parsed.err || !isObject(parsed.value)) {
63 // pass through
64 return inputData + EOL
65 }
66 log = parsed.value
67 } else {
68 log = inputData
69 }
70
71 // Short-circuit for spec allowed primitive values.
72 if ([null, true, false].includes(log) || Number.isFinite(log)) {
73 return `${log}\n`
74 }
75
76 if (search && !jmespath.search(log, search)) {
77 return
78 }
79
80 const prettifiedMessage = prettifyMessage({ log, messageKey, colorizer, messageFormat })
81
82 if (ignoreKeys) {
83 log = Object.keys(log)
84 .filter(key => !ignoreKeys.has(key))
85 .reduce((res, key) => {
86 res[key] = log[key]
87 return res
88 }, {})
89 }
90
91 const prettifiedLevel = prettifyLevel({ log, colorizer })
92 const prettifiedMetadata = prettifyMetadata({ log })
93 const prettifiedTime = prettifyTime({ log, translateFormat: opts.translateTime, timestampKey })
94
95 let line = ''
96 if (opts.levelFirst && prettifiedLevel) {
97 line = `${prettifiedLevel}`
98 }
99
100 if (prettifiedTime && line === '') {
101 line = `${prettifiedTime}`
102 } else if (prettifiedTime) {
103 line = `${line} ${prettifiedTime}`
104 }
105
106 if (!opts.levelFirst && prettifiedLevel) {
107 if (line.length > 0) {
108 line = `${line} ${prettifiedLevel}`
109 } else {
110 line = prettifiedLevel
111 }
112 }
113
114 if (prettifiedMetadata) {
115 line = `${line} ${prettifiedMetadata}:`
116 }
117
118 if (line.endsWith(':') === false && line !== '') {
119 line += ':'
120 }
121
122 if (prettifiedMessage) {
123 line = `${line} ${prettifiedMessage}`
124 }
125
126 if (line.length > 0) {
127 line += EOL
128 }
129
130 if (log.type === 'Error' && log.stack) {
131 const prettifiedErrorLog = prettifyErrorLog({
132 log,
133 errorLikeKeys: errorLikeObjectKeys,
134 errorProperties: errorProps,
135 ident: IDENT,
136 eol: EOL
137 })
138 line += prettifiedErrorLog
139 } else {
140 const skipKeys = typeof log[messageKey] === 'string' ? [messageKey] : undefined
141 const prettifiedObject = prettifyObject({
142 input: log,
143 skipKeys,
144 customPrettifiers,
145 errorLikeKeys: errorLikeObjectKeys,
146 eol: EOL,
147 ident: IDENT
148 })
149 line += prettifiedObject
150 }
151
152 return line
153 }
154}