trouble-in-terror-town/node_modules/npmlog/lib/log.js
Mikolaj 2bbacbea09 did some more work on networking and removed EOS in favor of LRM
did some more work on networking and removed EOS in favor of Light Reflective Mirror
2022-05-31 15:04:31 +02:00

404 lines
8.8 KiB
JavaScript

'use strict'
var Progress = require('are-we-there-yet')
var Gauge = require('gauge')
var EE = require('events').EventEmitter
var log = exports = module.exports = new EE()
var util = require('util')
var setBlocking = require('set-blocking')
var consoleControl = require('console-control-strings')
setBlocking(true)
var stream = process.stderr
Object.defineProperty(log, 'stream', {
set: function (newStream) {
stream = newStream
if (this.gauge) {
this.gauge.setWriteTo(stream, stream)
}
},
get: function () {
return stream
},
})
// by default, decide based on tty-ness.
var colorEnabled
log.useColor = function () {
return colorEnabled != null ? colorEnabled : stream.isTTY
}
log.enableColor = function () {
colorEnabled = true
this.gauge.setTheme({ hasColor: colorEnabled, hasUnicode: unicodeEnabled })
}
log.disableColor = function () {
colorEnabled = false
this.gauge.setTheme({ hasColor: colorEnabled, hasUnicode: unicodeEnabled })
}
// default level
log.level = 'info'
log.gauge = new Gauge(stream, {
enabled: false, // no progress bars unless asked
theme: { hasColor: log.useColor() },
template: [
{ type: 'progressbar', length: 20 },
{ type: 'activityIndicator', kerning: 1, length: 1 },
{ type: 'section', default: '' },
':',
{ type: 'logline', kerning: 1, default: '' },
],
})
log.tracker = new Progress.TrackerGroup()
// we track this separately as we may need to temporarily disable the
// display of the status bar for our own loggy purposes.
log.progressEnabled = log.gauge.isEnabled()
var unicodeEnabled
log.enableUnicode = function () {
unicodeEnabled = true
this.gauge.setTheme({ hasColor: this.useColor(), hasUnicode: unicodeEnabled })
}
log.disableUnicode = function () {
unicodeEnabled = false
this.gauge.setTheme({ hasColor: this.useColor(), hasUnicode: unicodeEnabled })
}
log.setGaugeThemeset = function (themes) {
this.gauge.setThemeset(themes)
}
log.setGaugeTemplate = function (template) {
this.gauge.setTemplate(template)
}
log.enableProgress = function () {
if (this.progressEnabled) {
return
}
this.progressEnabled = true
this.tracker.on('change', this.showProgress)
if (this._paused) {
return
}
this.gauge.enable()
}
log.disableProgress = function () {
if (!this.progressEnabled) {
return
}
this.progressEnabled = false
this.tracker.removeListener('change', this.showProgress)
this.gauge.disable()
}
var trackerConstructors = ['newGroup', 'newItem', 'newStream']
var mixinLog = function (tracker) {
// mixin the public methods from log into the tracker
// (except: conflicts and one's we handle specially)
Object.keys(log).forEach(function (P) {
if (P[0] === '_') {
return
}
if (trackerConstructors.filter(function (C) {
return C === P
}).length) {
return
}
if (tracker[P]) {
return
}
if (typeof log[P] !== 'function') {
return
}
var func = log[P]
tracker[P] = function () {
return func.apply(log, arguments)
}
})
// if the new tracker is a group, make sure any subtrackers get
// mixed in too
if (tracker instanceof Progress.TrackerGroup) {
trackerConstructors.forEach(function (C) {
var func = tracker[C]
tracker[C] = function () {
return mixinLog(func.apply(tracker, arguments))
}
})
}
return tracker
}
// Add tracker constructors to the top level log object
trackerConstructors.forEach(function (C) {
log[C] = function () {
return mixinLog(this.tracker[C].apply(this.tracker, arguments))
}
})
log.clearProgress = function (cb) {
if (!this.progressEnabled) {
return cb && process.nextTick(cb)
}
this.gauge.hide(cb)
}
log.showProgress = function (name, completed) {
if (!this.progressEnabled) {
return
}
var values = {}
if (name) {
values.section = name
}
var last = log.record[log.record.length - 1]
if (last) {
values.subsection = last.prefix
var disp = log.disp[last.level] || last.level
var logline = this._format(disp, log.style[last.level])
if (last.prefix) {
logline += ' ' + this._format(last.prefix, this.prefixStyle)
}
logline += ' ' + last.message.split(/\r?\n/)[0]
values.logline = logline
}
values.completed = completed || this.tracker.completed()
this.gauge.show(values)
}.bind(log) // bind for use in tracker's on-change listener
// temporarily stop emitting, but don't drop
log.pause = function () {
this._paused = true
if (this.progressEnabled) {
this.gauge.disable()
}
}
log.resume = function () {
if (!this._paused) {
return
}
this._paused = false
var b = this._buffer
this._buffer = []
b.forEach(function (m) {
this.emitLog(m)
}, this)
if (this.progressEnabled) {
this.gauge.enable()
}
}
log._buffer = []
var id = 0
log.record = []
log.maxRecordSize = 10000
log.log = function (lvl, prefix, message) {
var l = this.levels[lvl]
if (l === undefined) {
return this.emit('error', new Error(util.format(
'Undefined log level: %j', lvl)))
}
var a = new Array(arguments.length - 2)
var stack = null
for (var i = 2; i < arguments.length; i++) {
var arg = a[i - 2] = arguments[i]
// resolve stack traces to a plain string.
if (typeof arg === 'object' && arg instanceof Error && arg.stack) {
Object.defineProperty(arg, 'stack', {
value: stack = arg.stack + '',
enumerable: true,
writable: true,
})
}
}
if (stack) {
a.unshift(stack + '\n')
}
message = util.format.apply(util, a)
var m = {
id: id++,
level: lvl,
prefix: String(prefix || ''),
message: message,
messageRaw: a,
}
this.emit('log', m)
this.emit('log.' + lvl, m)
if (m.prefix) {
this.emit(m.prefix, m)
}
this.record.push(m)
var mrs = this.maxRecordSize
var n = this.record.length - mrs
if (n > mrs / 10) {
var newSize = Math.floor(mrs * 0.9)
this.record = this.record.slice(-1 * newSize)
}
this.emitLog(m)
}.bind(log)
log.emitLog = function (m) {
if (this._paused) {
this._buffer.push(m)
return
}
if (this.progressEnabled) {
this.gauge.pulse(m.prefix)
}
var l = this.levels[m.level]
if (l === undefined) {
return
}
if (l < this.levels[this.level]) {
return
}
if (l > 0 && !isFinite(l)) {
return
}
// If 'disp' is null or undefined, use the lvl as a default
// Allows: '', 0 as valid disp
var disp = log.disp[m.level] != null ? log.disp[m.level] : m.level
this.clearProgress()
m.message.split(/\r?\n/).forEach(function (line) {
var heading = this.heading
if (heading) {
this.write(heading, this.headingStyle)
this.write(' ')
}
this.write(disp, log.style[m.level])
var p = m.prefix || ''
if (p) {
this.write(' ')
}
this.write(p, this.prefixStyle)
this.write(' ' + line + '\n')
}, this)
this.showProgress()
}
log._format = function (msg, style) {
if (!stream) {
return
}
var output = ''
if (this.useColor()) {
style = style || {}
var settings = []
if (style.fg) {
settings.push(style.fg)
}
if (style.bg) {
settings.push('bg' + style.bg[0].toUpperCase() + style.bg.slice(1))
}
if (style.bold) {
settings.push('bold')
}
if (style.underline) {
settings.push('underline')
}
if (style.inverse) {
settings.push('inverse')
}
if (settings.length) {
output += consoleControl.color(settings)
}
if (style.beep) {
output += consoleControl.beep()
}
}
output += msg
if (this.useColor()) {
output += consoleControl.color('reset')
}
return output
}
log.write = function (msg, style) {
if (!stream) {
return
}
stream.write(this._format(msg, style))
}
log.addLevel = function (lvl, n, style, disp) {
// If 'disp' is null or undefined, use the lvl as a default
if (disp == null) {
disp = lvl
}
this.levels[lvl] = n
this.style[lvl] = style
if (!this[lvl]) {
this[lvl] = function () {
var a = new Array(arguments.length + 1)
a[0] = lvl
for (var i = 0; i < arguments.length; i++) {
a[i + 1] = arguments[i]
}
return this.log.apply(this, a)
}.bind(this)
}
this.disp[lvl] = disp
}
log.prefixStyle = { fg: 'magenta' }
log.headingStyle = { fg: 'white', bg: 'black' }
log.style = {}
log.levels = {}
log.disp = {}
log.addLevel('silly', -Infinity, { inverse: true }, 'sill')
log.addLevel('verbose', 1000, { fg: 'cyan', bg: 'black' }, 'verb')
log.addLevel('info', 2000, { fg: 'green' })
log.addLevel('timing', 2500, { fg: 'green', bg: 'black' })
log.addLevel('http', 3000, { fg: 'green', bg: 'black' })
log.addLevel('notice', 3500, { fg: 'cyan', bg: 'black' })
log.addLevel('warn', 4000, { fg: 'black', bg: 'yellow' }, 'WARN')
log.addLevel('error', 5000, { fg: 'red', bg: 'black' }, 'ERR!')
log.addLevel('silent', Infinity)
// allow 'error' prefix
log.on('error', function () {})