-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfancy.js
147 lines (138 loc) · 3.85 KB
/
fancy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* Copyright (c) Maximilian Antoni <max@javascript.studio>
*
* @license MIT
*/
'use strict';
const Transform = require('stream').Transform;
const chalk = require('chalk');
const topics = require('@studio/log-topics');
const valueFormat = require('./lib/value-format');
const time = require('./lib/time');
const non_printable_ecapes = {
0: '\\0',
7: '\\a',
8: '\\b',
9: '\\t',
10: '\\n',
11: '\\v',
12: '\\f',
13: '\\r',
27: '\\e'
};
function escapeNonPrintable(m) {
const code = m.charCodeAt(0);
if (code > 128) {
return m;
}
const escape = non_printable_ecapes[code];
if (escape) {
return escape;
}
const hex = code.toString(16);
return hex.length === 1
? `\\x0${hex}`
: `\\x${hex}`;
}
function stringify(value) {
if (value === null || value === undefined) {
return chalk.bold(String(value));
}
const type = typeof value;
if (type === 'string') {
// https://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
const escaped = value
.replace(/'/g, '\\\'')
.replace(/[^\x20-\x7e]/g, escapeNonPrintable);
return chalk.green(`'${escaped}'`);
}
if (type === 'number' || type === 'boolean') {
return chalk.yellow(value);
}
if (value instanceof Date) {
return chalk.yellow(value.toLocaleString());
}
if (Array.isArray(value)) {
const values = value.map(stringify).join(chalk.magenta(', '));
return `${chalk.magenta('[')}${values}${chalk.magenta(']')}`;
}
const values = Object.keys(value).map((k) => {
const v = stringify(value[k]);
return `${k}${chalk.magenta(':')} ${v}`;
}).join(chalk.magenta(', '));
if (values) {
return `${chalk.magenta('{')} ${values} ${chalk.magenta('}')}`;
}
return chalk.magenta('{}');
}
function formatStack(style, stack) {
const p1 = stack.indexOf('\n');
const first_line = p1 === -1 ? stack : stack.substring(0, p1);
const formatted = chalk.bgRed.white.bold(first_line);
if (style === 'message' || p1 === -1) {
return formatted;
}
if (style === 'peek') {
const p2 = stack.indexOf('\n', p1 + 1);
const peek = p2 === -1
? stack.substring(p1 + 1)
: stack.substring(p1 + 1, p2);
return `${formatted} ${chalk.gray(peek.trim())}`;
}
const remainder = chalk.gray(stack.substring(p1 + 1));
return `${formatted}\n${remainder}`;
}
module.exports = class extends Transform {
constructor(opts) {
super({
writableObjectMode: true
});
opts = opts || {};
this.ts = opts.ts !== false;
this.topic = opts.topic !== false;
this.ns = opts.ns !== false;
this.data = opts.data !== false;
this.stack = opts.hasOwnProperty('stack') ? opts.stack : 'peek';
}
_transform(entry, enc, callback) {
const parts = [];
if (this.ts) {
parts.push(chalk.gray(time(new Date(entry.ts))));
}
if (this.topic) {
parts.push(topics[entry.topic]);
}
if (this.ns) {
parts.push(chalk.blue(entry.ns));
}
if (entry.msg) {
parts.push(entry.msg);
}
if (this.data && entry.data) {
if (typeof entry.data === 'object') {
for (const key in entry.data) {
if (entry.data.hasOwnProperty(key)) {
const value = entry.data[key];
const kvu = valueFormat(key, value, stringify);
const k = kvu[0];
const v = kvu[1];
const unit = kvu[2];
const highlighted = unit ? `${chalk.yellow(v)}${unit}` : v;
parts.push(k ? `${chalk.bold(k)}=${highlighted}` : highlighted);
}
}
} else {
parts.push(stringify(entry.data));
}
}
if (this.stack && entry.stack) {
parts.push(formatStack(this.stack, entry.stack));
}
let str = parts.join(' ');
if (this.stack && entry.cause) {
str += `\n ${chalk.magenta('caused by')} ${
formatStack(this.stack, entry.cause)}`;
}
callback(null, `${str}\n`);
}
};