UNPKG

3.68 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 timestampKey: TIMESTAMP_KEY,
34 translateTime: false,
35 useMetadata: false,
36 outputStream: process.stdout
37}
38
39module.exports = function prettyFactory (options) {
40 const opts = Object.assign({}, defaultOptions, options)
41 const EOL = opts.crlf ? '\r\n' : '\n'
42 const IDENT = ' '
43 const messageKey = opts.messageKey
44 const timestampKey = opts.timestampKey
45 const errorLikeObjectKeys = opts.errorLikeObjectKeys
46 const errorProps = opts.errorProps.split(',')
47 const ignoreKeys = opts.ignore ? new Set(opts.ignore.split(',')) : undefined
48
49 const colorizer = colors(opts.colorize)
50 const search = opts.search
51
52 return pretty
53
54 function pretty (inputData) {
55 let log
56 if (!isObject(inputData)) {
57 const parsed = jsonParser(inputData)
58 log = parsed.value
59 if (parsed.err) {
60 // pass through
61 return inputData + EOL
62 }
63 } else {
64 log = inputData
65 }
66
67 // Short-circuit for spec allowed primitive values.
68 if ([null, true, false].includes(log)) {
69 return `${log}\n`
70 }
71
72 if (search && !jmespath.search(log, search)) {
73 return
74 }
75
76 if (ignoreKeys) {
77 log = Object.keys(log)
78 .filter(key => !ignoreKeys.has(key))
79 .reduce((res, key) => {
80 res[key] = log[key]
81 return res
82 }, {})
83 }
84
85 const prettifiedLevel = prettifyLevel({ log, colorizer })
86 const prettifiedMessage = prettifyMessage({ log, messageKey, colorizer })
87 const prettifiedMetadata = prettifyMetadata({ log })
88 const prettifiedTime = prettifyTime({ log, translateFormat: opts.translateTime, timestampKey })
89
90 let line = ''
91 if (opts.levelFirst && prettifiedLevel) {
92 line = `${prettifiedLevel}`
93 }
94
95 if (prettifiedTime && line === '') {
96 line = `${prettifiedTime}`
97 } else if (prettifiedTime) {
98 line = `${line} ${prettifiedTime}`
99 }
100
101 if (!opts.levelFirst && prettifiedLevel) {
102 if (line.length > 0) {
103 line = `${line} ${prettifiedLevel}`
104 } else {
105 line = prettifiedLevel
106 }
107 }
108
109 if (prettifiedMetadata) {
110 line = `${line} ${prettifiedMetadata}:`
111 }
112
113 if (line.endsWith(':') === false && line !== '') {
114 line += ':'
115 }
116
117 if (prettifiedMessage) {
118 line = `${line} ${prettifiedMessage}`
119 }
120
121 if (line.length > 0) {
122 line += EOL
123 }
124
125 if (log.type === 'Error' && log.stack) {
126 const prettifiedErrorLog = prettifyErrorLog({
127 log,
128 errorLikeKeys: errorLikeObjectKeys,
129 errorProperties: errorProps,
130 ident: IDENT,
131 eol: EOL
132 })
133 line += prettifiedErrorLog
134 } else {
135 const skipKeys = typeof log[messageKey] === 'string' ? [messageKey] : undefined
136 const prettifiedObject = prettifyObject({
137 input: log,
138 skipKeys,
139 errorLikeKeys: errorLikeObjectKeys,
140 eol: EOL,
141 ident: IDENT
142 })
143 line += prettifiedObject
144 }
145
146 return line
147 }
148}