UNPKG

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