source: node_modules/npmlog/lib/log.js@ 62b2964

finki-main main
Last change on this file since 62b2964 was 81bc7da, checked in by Klimentina Efremova <klimentina08642@…>, 3 months ago

Initial commit

  • Property mode set to 100644
File size: 8.8 KB
Line 
1'use strict'
2var Progress = require('are-we-there-yet')
3var Gauge = require('gauge')
4var EE = require('events').EventEmitter
5var log = exports = module.exports = new EE()
6var util = require('util')
7
8var setBlocking = require('set-blocking')
9var consoleControl = require('console-control-strings')
10
11setBlocking(true)
12var stream = process.stderr
13Object.defineProperty(log, 'stream', {
14 set: function (newStream) {
15 stream = newStream
16 if (this.gauge) {
17 this.gauge.setWriteTo(stream, stream)
18 }
19 },
20 get: function () {
21 return stream
22 },
23})
24
25// by default, decide based on tty-ness.
26var colorEnabled
27log.useColor = function () {
28 return colorEnabled != null ? colorEnabled : stream.isTTY
29}
30
31log.enableColor = function () {
32 colorEnabled = true
33 this.gauge.setTheme({ hasColor: colorEnabled, hasUnicode: unicodeEnabled })
34}
35log.disableColor = function () {
36 colorEnabled = false
37 this.gauge.setTheme({ hasColor: colorEnabled, hasUnicode: unicodeEnabled })
38}
39
40// default level
41log.level = 'info'
42
43log.gauge = new Gauge(stream, {
44 enabled: false, // no progress bars unless asked
45 theme: { hasColor: log.useColor() },
46 template: [
47 { type: 'progressbar', length: 20 },
48 { type: 'activityIndicator', kerning: 1, length: 1 },
49 { type: 'section', default: '' },
50 ':',
51 { type: 'logline', kerning: 1, default: '' },
52 ],
53})
54
55log.tracker = new Progress.TrackerGroup()
56
57// we track this separately as we may need to temporarily disable the
58// display of the status bar for our own loggy purposes.
59log.progressEnabled = log.gauge.isEnabled()
60
61var unicodeEnabled
62
63log.enableUnicode = function () {
64 unicodeEnabled = true
65 this.gauge.setTheme({ hasColor: this.useColor(), hasUnicode: unicodeEnabled })
66}
67
68log.disableUnicode = function () {
69 unicodeEnabled = false
70 this.gauge.setTheme({ hasColor: this.useColor(), hasUnicode: unicodeEnabled })
71}
72
73log.setGaugeThemeset = function (themes) {
74 this.gauge.setThemeset(themes)
75}
76
77log.setGaugeTemplate = function (template) {
78 this.gauge.setTemplate(template)
79}
80
81log.enableProgress = function () {
82 if (this.progressEnabled) {
83 return
84 }
85
86 this.progressEnabled = true
87 this.tracker.on('change', this.showProgress)
88 if (this._paused) {
89 return
90 }
91
92 this.gauge.enable()
93}
94
95log.disableProgress = function () {
96 if (!this.progressEnabled) {
97 return
98 }
99 this.progressEnabled = false
100 this.tracker.removeListener('change', this.showProgress)
101 this.gauge.disable()
102}
103
104var trackerConstructors = ['newGroup', 'newItem', 'newStream']
105
106var mixinLog = function (tracker) {
107 // mixin the public methods from log into the tracker
108 // (except: conflicts and one's we handle specially)
109 Object.keys(log).forEach(function (P) {
110 if (P[0] === '_') {
111 return
112 }
113
114 if (trackerConstructors.filter(function (C) {
115 return C === P
116 }).length) {
117 return
118 }
119
120 if (tracker[P]) {
121 return
122 }
123
124 if (typeof log[P] !== 'function') {
125 return
126 }
127
128 var func = log[P]
129 tracker[P] = function () {
130 return func.apply(log, arguments)
131 }
132 })
133 // if the new tracker is a group, make sure any subtrackers get
134 // mixed in too
135 if (tracker instanceof Progress.TrackerGroup) {
136 trackerConstructors.forEach(function (C) {
137 var func = tracker[C]
138 tracker[C] = function () {
139 return mixinLog(func.apply(tracker, arguments))
140 }
141 })
142 }
143 return tracker
144}
145
146// Add tracker constructors to the top level log object
147trackerConstructors.forEach(function (C) {
148 log[C] = function () {
149 return mixinLog(this.tracker[C].apply(this.tracker, arguments))
150 }
151})
152
153log.clearProgress = function (cb) {
154 if (!this.progressEnabled) {
155 return cb && process.nextTick(cb)
156 }
157
158 this.gauge.hide(cb)
159}
160
161log.showProgress = function (name, completed) {
162 if (!this.progressEnabled) {
163 return
164 }
165
166 var values = {}
167 if (name) {
168 values.section = name
169 }
170
171 var last = log.record[log.record.length - 1]
172 if (last) {
173 values.subsection = last.prefix
174 var disp = log.disp[last.level] || last.level
175 var logline = this._format(disp, log.style[last.level])
176 if (last.prefix) {
177 logline += ' ' + this._format(last.prefix, this.prefixStyle)
178 }
179
180 logline += ' ' + last.message.split(/\r?\n/)[0]
181 values.logline = logline
182 }
183 values.completed = completed || this.tracker.completed()
184 this.gauge.show(values)
185}.bind(log) // bind for use in tracker's on-change listener
186
187// temporarily stop emitting, but don't drop
188log.pause = function () {
189 this._paused = true
190 if (this.progressEnabled) {
191 this.gauge.disable()
192 }
193}
194
195log.resume = function () {
196 if (!this._paused) {
197 return
198 }
199
200 this._paused = false
201
202 var b = this._buffer
203 this._buffer = []
204 b.forEach(function (m) {
205 this.emitLog(m)
206 }, this)
207 if (this.progressEnabled) {
208 this.gauge.enable()
209 }
210}
211
212log._buffer = []
213
214var id = 0
215log.record = []
216log.maxRecordSize = 10000
217log.log = function (lvl, prefix, message) {
218 var l = this.levels[lvl]
219 if (l === undefined) {
220 return this.emit('error', new Error(util.format(
221 'Undefined log level: %j', lvl)))
222 }
223
224 var a = new Array(arguments.length - 2)
225 var stack = null
226 for (var i = 2; i < arguments.length; i++) {
227 var arg = a[i - 2] = arguments[i]
228
229 // resolve stack traces to a plain string.
230 if (typeof arg === 'object' && arg instanceof Error && arg.stack) {
231 Object.defineProperty(arg, 'stack', {
232 value: stack = arg.stack + '',
233 enumerable: true,
234 writable: true,
235 })
236 }
237 }
238 if (stack) {
239 a.unshift(stack + '\n')
240 }
241 message = util.format.apply(util, a)
242
243 var m = {
244 id: id++,
245 level: lvl,
246 prefix: String(prefix || ''),
247 message: message,
248 messageRaw: a,
249 }
250
251 this.emit('log', m)
252 this.emit('log.' + lvl, m)
253 if (m.prefix) {
254 this.emit(m.prefix, m)
255 }
256
257 this.record.push(m)
258 var mrs = this.maxRecordSize
259 var n = this.record.length - mrs
260 if (n > mrs / 10) {
261 var newSize = Math.floor(mrs * 0.9)
262 this.record = this.record.slice(-1 * newSize)
263 }
264
265 this.emitLog(m)
266}.bind(log)
267
268log.emitLog = function (m) {
269 if (this._paused) {
270 this._buffer.push(m)
271 return
272 }
273 if (this.progressEnabled) {
274 this.gauge.pulse(m.prefix)
275 }
276
277 var l = this.levels[m.level]
278 if (l === undefined) {
279 return
280 }
281
282 if (l < this.levels[this.level]) {
283 return
284 }
285
286 if (l > 0 && !isFinite(l)) {
287 return
288 }
289
290 // If 'disp' is null or undefined, use the lvl as a default
291 // Allows: '', 0 as valid disp
292 var disp = log.disp[m.level] != null ? log.disp[m.level] : m.level
293 this.clearProgress()
294 m.message.split(/\r?\n/).forEach(function (line) {
295 var heading = this.heading
296 if (heading) {
297 this.write(heading, this.headingStyle)
298 this.write(' ')
299 }
300 this.write(disp, log.style[m.level])
301 var p = m.prefix || ''
302 if (p) {
303 this.write(' ')
304 }
305
306 this.write(p, this.prefixStyle)
307 this.write(' ' + line + '\n')
308 }, this)
309 this.showProgress()
310}
311
312log._format = function (msg, style) {
313 if (!stream) {
314 return
315 }
316
317 var output = ''
318 if (this.useColor()) {
319 style = style || {}
320 var settings = []
321 if (style.fg) {
322 settings.push(style.fg)
323 }
324
325 if (style.bg) {
326 settings.push('bg' + style.bg[0].toUpperCase() + style.bg.slice(1))
327 }
328
329 if (style.bold) {
330 settings.push('bold')
331 }
332
333 if (style.underline) {
334 settings.push('underline')
335 }
336
337 if (style.inverse) {
338 settings.push('inverse')
339 }
340
341 if (settings.length) {
342 output += consoleControl.color(settings)
343 }
344
345 if (style.beep) {
346 output += consoleControl.beep()
347 }
348 }
349 output += msg
350 if (this.useColor()) {
351 output += consoleControl.color('reset')
352 }
353
354 return output
355}
356
357log.write = function (msg, style) {
358 if (!stream) {
359 return
360 }
361
362 stream.write(this._format(msg, style))
363}
364
365log.addLevel = function (lvl, n, style, disp) {
366 // If 'disp' is null or undefined, use the lvl as a default
367 if (disp == null) {
368 disp = lvl
369 }
370
371 this.levels[lvl] = n
372 this.style[lvl] = style
373 if (!this[lvl]) {
374 this[lvl] = function () {
375 var a = new Array(arguments.length + 1)
376 a[0] = lvl
377 for (var i = 0; i < arguments.length; i++) {
378 a[i + 1] = arguments[i]
379 }
380
381 return this.log.apply(this, a)
382 }.bind(this)
383 }
384 this.disp[lvl] = disp
385}
386
387log.prefixStyle = { fg: 'magenta' }
388log.headingStyle = { fg: 'white', bg: 'black' }
389
390log.style = {}
391log.levels = {}
392log.disp = {}
393log.addLevel('silly', -Infinity, { inverse: true }, 'sill')
394log.addLevel('verbose', 1000, { fg: 'cyan', bg: 'black' }, 'verb')
395log.addLevel('info', 2000, { fg: 'green' })
396log.addLevel('timing', 2500, { fg: 'green', bg: 'black' })
397log.addLevel('http', 3000, { fg: 'green', bg: 'black' })
398log.addLevel('notice', 3500, { fg: 'cyan', bg: 'black' })
399log.addLevel('warn', 4000, { fg: 'black', bg: 'yellow' }, 'WARN')
400log.addLevel('error', 5000, { fg: 'red', bg: 'black' }, 'ERR!')
401log.addLevel('silent', Infinity)
402
403// allow 'error' prefix
404log.on('error', function () {})
Note: See TracBrowser for help on using the repository browser.