-
Notifications
You must be signed in to change notification settings - Fork 12k
/
Copy pathcli-logger.ts
75 lines (70 loc) · 2.86 KB
/
cli-logger.ts
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
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { filter } from 'rxjs/operators';
import { logging, terminal } from '../src';
export interface ProcessOutput {
write(buffer: string | Buffer): boolean;
}
/**
* A Logger that sends information to STDOUT and STDERR.
*/
export function createConsoleLogger(
verbose = false,
stdout: ProcessOutput = process.stdout,
stderr: ProcessOutput = process.stderr,
): logging.Logger {
const logger = new logging.IndentLogger('cling');
logger
.pipe(filter(entry => (entry.level != 'debug' || verbose)))
.subscribe(entry => {
let color: (s: string) => string = x => terminal.dim(terminal.white(x));
let output = stdout;
switch (entry.level) {
case 'info':
color = terminal.white;
break;
case 'warn':
color = (x: string) => terminal.bold(terminal.yellow(x));
output = stderr;
break;
case 'fatal':
case 'error':
color = (x: string) => terminal.bold(terminal.red(x));
output = stderr;
break;
}
// If we do console.log(message) or process.stdout.write(message + '\n'), the process might
// stop before the whole message is written and the stream is flushed. This happens when
// streams are asynchronous.
//
// NodeJS IO streams are different depending on platform and usage. In POSIX environment,
// for example, they're asynchronous when writing to a pipe, but synchronous when writing
// to a TTY. In windows, it's the other way around. You can verify which is which with
// stream.isTTY and platform, but this is not good enough.
// In the async case, one should wait for the callback before sending more data or
// continuing the process. In our case it would be rather hard to do (but not impossible).
//
// Instead we take the easy way out and simply chunk the message and call the write
// function while the buffer drain itself asynchronously. With a smaller chunk size than
// the buffer, we are mostly certain that it works. In this case, the chunk has been picked
// as half a page size (4096/2 = 2048), minus some bytes for the color formatting.
// On POSIX it seems the buffer is 2 pages (8192), but just to be sure (could be different
// by platform).
//
// For more details, see https://nodejs.org/api/process.html#process_a_note_on_process_i_o
const chunkSize = 2000; // Small chunk.
let message = entry.message;
while (message) {
const chunk = message.slice(0, chunkSize);
message = message.slice(chunkSize);
output.write(color(chunk));
}
output.write('\n');
});
return logger;
}