UNPKG

3.58 kBJavaScriptView Raw
1#!/usr/bin/env node
2
3'use strict';
4
5const args = require('minimist')(process.argv.slice(2));
6const bunyan = require('./bunyan');
7const dargs = require('dargs');
8const dedent = require('dedent');
9const JoyCon = require('joycon');
10const path = require('path');
11const { readFileSync } = require('fs');
12const stripJsonComments = require('strip-json-comments');
13
14const isFunction = arg => typeof arg === 'function';
15const isObject = arg => arg !== null && typeof arg === 'object';
16
17const parseJSON = input => JSON.parse(stripJsonComments(input));
18const joycon = new JoyCon({
19 parseJSON,
20 files: [
21 'bunyan-pretty.config.js',
22 '.bunyan-prettyrc',
23 '.bunyan-prettyrc.json'
24 ],
25 stopDir: path.dirname(process.cwd())
26});
27joycon.addLoader({
28 test: /\.[^.]*rc$/,
29 loadSync: path => parseJSON(readFileSync(path, 'utf-8'))
30});
31
32const { emitRecord: _emitRecord } = bunyan;
33bunyan.emitRecord = emitRecord;
34
35const { parseArgv: _parseArgv } = bunyan;
36bunyan.parseArgv = parseArgv;
37
38const { printHelp: _printHelp } = bunyan;
39bunyan.printHelp = printHelp;
40
41main(args);
42
43function main({ config, ...args }) {
44 const argv = process.argv.slice(0);
45 argv.length = 2;
46 argv.push(...dargs(args, { useEquals: false }));
47 bunyan.main(argv);
48}
49
50function parseArgv(input) {
51 const { levelFromName, OM_FROM_NAME } = bunyan;
52 const { _defaults: defaultOptions, ...options } = _parseArgv.call(this, input);
53 const config = loadConfig(args.config);
54 if (config.level) config.level = levelFromName[config.level.toLowerCase()];
55 if (config.outputMode) config.outputMode = OM_FROM_NAME[config.outputMode];
56 return Object.assign({}, defaultOptions, config, options);
57}
58
59function printHelp() {
60 let help = '';
61 const { print: _print } = bunyan;
62 bunyan.print = input => (help += '\n' + input);
63 _printHelp.call(this);
64 help = help.trimLeft();
65 help = help.replace(/General options:/, header => dedent`
66 ${header}
67 --config specify path to config file containing bunyan-pretty
68 options. bunyan-pretty will atempt to read from a
69 \`.bunyan-prettyrc\` in current working directory if
70 not specified
71 `);
72 help = help.replace(/bunyan(\s)/g, 'bunyan-pretty$1');
73 bunyan.print = _print;
74 _print(help);
75}
76
77function emitRecord(record, line, options, stylize) {
78 const { emit: _emit, indent, isValidRecord, OM_LONG, OM_SHORT } = bunyan;
79 const { outputMode, customPrettifiers = {} } = options;
80 if (![OM_LONG, OM_SHORT].includes(outputMode) || !isValidRecord(record)) {
81 return _emitRecord.apply(this, arguments);
82 }
83 let extras = '';
84 const newRecord = Object.entries(record).reduce((acc, [key, value]) => {
85 const customPrettifier = customPrettifiers[key];
86 if (!isFunction(customPrettifier)) {
87 return Object.assign(acc, { [key]: value });
88 }
89 extras += indent(`${key}: ${customPrettifier(value, key, record)}`) + '\n';
90 return acc;
91 }, {});
92 bunyan.emit = input => _emit(input + extras);
93 const result = _emitRecord.call(this, newRecord, line, options, stylize);
94 bunyan.emit = _emit;
95 return result;
96}
97
98function loadConfig(configPath) {
99 const files = configPath ? [path.resolve(configPath)] : undefined;
100 const result = joycon.loadSync(files);
101 if (result.path && !isObject(result.data)) {
102 configPath = configPath || path.basename(result.path);
103 throw new Error(`Invalid runtime configuration file: ${configPath}`);
104 }
105 if (configPath && !result.data) {
106 throw new Error(`Failed to load runtime configuration file: ${configPath}`);
107 }
108 return result.data || {};
109}