forked from arne/asdf-games
193 lines
4.5 KiB
JavaScript
193 lines
4.5 KiB
JavaScript
|
var chalk = require('chalk')
|
||
|
var stripUrl = require('url-trim')
|
||
|
var now = require('right-now')
|
||
|
var levels = require('./levels')
|
||
|
var padLeft = require('pad-left')
|
||
|
var padRight = require('pad-right')
|
||
|
var prettyBytes = require('prettier-bytes')
|
||
|
var prettyMs = require('pretty-ms')
|
||
|
|
||
|
var paddings = {
|
||
|
method: 6,
|
||
|
statusCode: 3,
|
||
|
contentLength: 8,
|
||
|
elapsed: 7
|
||
|
}
|
||
|
|
||
|
var leftAligns = [ 'method' ]
|
||
|
|
||
|
var ansiStyles = Object.keys(chalk.styles)
|
||
|
var keys = [
|
||
|
'time',
|
||
|
'level',
|
||
|
'elapsed',
|
||
|
'contentLength',
|
||
|
'message',
|
||
|
'method',
|
||
|
'statusCode',
|
||
|
'url',
|
||
|
'type',
|
||
|
'name'
|
||
|
]
|
||
|
|
||
|
var startTime = now()
|
||
|
|
||
|
exports.isStyleObject = function (data) {
|
||
|
// skip false/undefined/etc
|
||
|
if (typeof data !== 'object' || !data) {
|
||
|
return false
|
||
|
}
|
||
|
// ensure we have something worth styling
|
||
|
return keys.some(function (key) {
|
||
|
return data.hasOwnProperty(key)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
exports.renderError = function (data) {
|
||
|
var timeOff = String(Math.round((now() - startTime) / 1000) % 10000)
|
||
|
var line = '[' + padLeft(timeOff, 4, '0') + '] '
|
||
|
line += chalk['magenta']('(' + data.name + ')') + '\n'
|
||
|
line += chalk.red(data.err.stack) + '\n'
|
||
|
return line
|
||
|
}
|
||
|
|
||
|
exports.renderObject = function (data) {
|
||
|
var timeOff = String(Math.round((now() - startTime) / 1000) % 10000)
|
||
|
var line = ''
|
||
|
line += '[' + padLeft(timeOff, 4, '0') + '] '
|
||
|
line += levels.stringify(data.level)
|
||
|
line += chalk['magenta']('(' + data.name + ')') + '\n'
|
||
|
line += destructureMessage(data.message)
|
||
|
return line
|
||
|
}
|
||
|
|
||
|
exports.create = function (defaultName) {
|
||
|
return function render (data) {
|
||
|
var level = data.level
|
||
|
var name = data.name
|
||
|
|
||
|
// some default colors
|
||
|
var defaultColors = {
|
||
|
level: levels.color(level) || 'yellow',
|
||
|
name: 'magenta',
|
||
|
time: 'dim',
|
||
|
statusCode: data.statusCode >= 400 ? 'red' : 'green',
|
||
|
contentLength: 'dim',
|
||
|
elapsed: 'dim',
|
||
|
url: 'bold',
|
||
|
method: 'dim',
|
||
|
type: 'dim'
|
||
|
}
|
||
|
|
||
|
// possible user overrides
|
||
|
var colors = data.colors || {}
|
||
|
|
||
|
if (typeof data.message === 'object') {
|
||
|
data.message = destructureMessage(data.message)
|
||
|
}
|
||
|
|
||
|
// clean up the messages a little
|
||
|
if (level) {
|
||
|
data.level = levels.stringify(level)
|
||
|
}
|
||
|
|
||
|
if (name) {
|
||
|
data.name = name === defaultName ? '' : ('(' + name + ')')
|
||
|
}
|
||
|
|
||
|
if (data.url) data.url = stripUrl(data.url)
|
||
|
if (data.type) data.type = '(' + data.type + ')'
|
||
|
|
||
|
var line = []
|
||
|
var timeOff = String(Math.round((now() - startTime) / 1000) % 10000)
|
||
|
data.time = '[' + padLeft(timeOff, 4, '0') + ']'
|
||
|
|
||
|
if (!data.message) {
|
||
|
data.level = level = ''
|
||
|
}
|
||
|
|
||
|
var alignLeft = true
|
||
|
|
||
|
// render each of our valid keys
|
||
|
keys.forEach(function (key) {
|
||
|
var value = data[key]
|
||
|
|
||
|
// skip empty data
|
||
|
if (!value && typeof value !== 'number') {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// compact formatting
|
||
|
if (key === 'elapsed') value = fixElapsed(value)
|
||
|
if (key === 'contentLength') value = fixSize(value)
|
||
|
|
||
|
// pad to length
|
||
|
if (key in paddings) {
|
||
|
var left = alignLeft || leftAligns.indexOf(key) >= 0
|
||
|
var padFn = left ? padRight : padLeft
|
||
|
value = padFn.call(padFn, value, paddings[key], ' ')
|
||
|
alignLeft = false
|
||
|
}
|
||
|
|
||
|
// colorize chunk
|
||
|
var newColor = getColor(key, colors, defaultColors)
|
||
|
|
||
|
if (newColor) {
|
||
|
value = chalk[newColor](value)
|
||
|
}
|
||
|
|
||
|
line.push(value)
|
||
|
})
|
||
|
return line.join(' ')
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function fixElapsed (time) {
|
||
|
if (typeof time === 'string' && /s$/i.test(time)) {
|
||
|
return time
|
||
|
}
|
||
|
if (/infinity/i.test(time)) return time
|
||
|
var ms = parseInt(time, 10)
|
||
|
return ms > 9999 ? prettyMs(ms) : (ms + 'ms')
|
||
|
}
|
||
|
|
||
|
function fixSize (size) {
|
||
|
if (typeof size === 'string' && /s$/i.test(size)) {
|
||
|
return size
|
||
|
}
|
||
|
if (/infinity/i.test(size)) return size
|
||
|
var bytes = parseInt(size, 10)
|
||
|
return bytes > 9999
|
||
|
? prettyBytes(bytes)
|
||
|
.replace(/ /, '')
|
||
|
: (bytes + 'B')
|
||
|
}
|
||
|
|
||
|
function getColor (key, colors, defaultColors) {
|
||
|
// try to apply user style
|
||
|
var newColor = colors[key]
|
||
|
|
||
|
// use default if style is invalid
|
||
|
if (ansiStyles.indexOf(newColor) === -1) {
|
||
|
newColor = null
|
||
|
}
|
||
|
return newColor || defaultColors[key]
|
||
|
}
|
||
|
|
||
|
// destructure a message onto an object if the message
|
||
|
// is an object.
|
||
|
// obj -> str
|
||
|
function destructureMessage (msg) {
|
||
|
const keys = Object.keys(msg)
|
||
|
var res = ''
|
||
|
for (var i = 0; i < keys.length; i++) {
|
||
|
var key = keys[i]
|
||
|
var val = msg[key]
|
||
|
if (i !== 0) res += '\n'
|
||
|
res += chalk.blue(' "' + key + '"')
|
||
|
res += ': '
|
||
|
res += chalk.green('"' + val + '"')
|
||
|
}
|
||
|
return res
|
||
|
}
|