UNPKG

verdaccio

Version:
207 lines (187 loc) 5.07 kB
'use strict'; const Logger = require('bunyan'); const Error = require('http-errors'); const Stream = require('stream'); const chalk = require('chalk'); const Utils = require('./utils'); const pkgJSON = require('../../package.json'); /** * Match the level based on buyan severity scale * @param {*} x severity level * @return {String} security level */ function getlvl(x) { switch (true) { case x < 15: return 'trace'; case x < 25: return 'debug'; case x < 35: return 'info'; case x == 35: return 'http'; case x < 45: return 'warn'; case x < 55: return 'error'; default: return 'fatal'; } } /** * Setup the Buyan logger * @param {*} logs list of log configuration */ function setup(logs) { let streams = []; if (logs == null) { logs = [{ type: 'stdout', format: 'pretty', level: 'http' }]; } logs.forEach(function (target) { // create a stream for each log configuration const stream = new Stream(); stream.writable = true; if (target.type === 'stdout' || target.type === 'stderr') { // destination stream const dest = target.type === 'stdout' ? process.stdout : process.stderr; if (target.format === 'pretty') { // making fake stream for prettypritting stream.write = function (obj) { dest.write(print(obj.level, obj.msg, obj, dest.isTTY) + '\n'); }; } else if (target.format === 'pretty-timestamped') { // making fake stream for prettypritting stream.write = function (obj) { dest.write(obj.time.toISOString() + print(obj.level, obj.msg, obj, dest.isTTY) + '\n'); }; } else { stream.write = function (obj) { dest.write(JSON.stringify(obj, Logger.safeCycles()) + '\n'); }; } } else if (target.type === 'file') { const dest = require('fs').createWriteStream(target.path, { flags: 'a', encoding: 'utf8' }); dest.on('error', function (err) { Logger.emit('error', err); }); stream.write = function (obj) { if (target.format === 'pretty') { dest.write(print(obj.level, obj.msg, obj, false) + '\n'); } else { dest.write(JSON.stringify(obj, Logger.safeCycles()) + '\n'); } }; } else { throw Error('wrong target type for a log'); } if (target.level === 'http') target.level = 35; streams.push({ type: 'raw', level: target.level || 35, stream: stream }); }); // buyan default configuration const logger = new Logger({ name: pkgJSON.name, streams: streams, serializers: { err: Logger.stdSerializers.err, req: Logger.stdSerializers.req, res: Logger.stdSerializers.res } }); process.on('SIGUSR2', function () { Logger.reopenFileStreams(); }); module.exports.logger = logger; } // adopted from socket.io // this part was converted to coffee-script and back again over the years, // so it might look weird // level to color const levels = { fatal: chalk.red, error: chalk.red, warn: chalk.yellow, http: chalk.magenta, info: chalk.cyan, debug: chalk.green, trace: chalk.white }; let max = 0; for (let l in levels) { if (Object.prototype.hasOwnProperty.call(levels, l)) { max = Math.max(max, l.length); } } /** * Apply whitespaces based on the length * @param {*} str the log message * @return {String} */ function pad(str) { if (str.length < max) { return str + ' '.repeat(max - str.length); } return str; } /** * Apply colors to a string based on level parameters. * @param {*} type * @param {*} msg * @param {*} obj * @param {*} colors * @return {String} */ function print(type, msg, obj, colors) { if (typeof type === 'number') { type = getlvl(type); } let finalmsg = msg.replace(/@{(!?[$A-Za-z_][$0-9A-Za-z\._]*)}/g, function (_, name) { let str = obj; let is_error; if (name[0] === '!') { name = name.substr(1); is_error = true; } let _ref = name.split('.'); for (let _i = 0; _i < _ref.length; _i++) { let id = _ref[_i]; if (Utils.isObject(str) || Array.isArray(str)) { str = str[id]; } else { str = undefined; } } if (typeof str === 'string') { if (!colors || str.includes('\n')) { return str; } else if (is_error) { return chalk.red(str); } else { return chalk.green(str); } } else { return require('util').inspect(str, null, null, colors); } }); const subsystems = [{ in: chalk.green('<--'), out: chalk.yellow('-->'), fs: chalk.black('-=-'), default: chalk.blue('---') }, { in: '<--', out: '-->', fs: '-=-', default: '---' }]; const sub = subsystems[colors ? 0 : 1][obj.sub] || subsystems[+!colors].default; if (colors) { return ` ${levels[type](pad(type))}${chalk.white(`${sub} ${finalmsg}`)}`; } else { return ` ${pad(type)}${sub} ${finalmsg}`; } } module.exports.setup = setup;