| 19 | * @deprecated Use a custom logger implementation instead. |
| 20 | */ |
| 21 | export function createConsoleLogger( |
| 22 | verbose = false, |
| 23 | stdout: ProcessOutput = process.stdout, |
| 24 | stderr: ProcessOutput = process.stderr, |
| 25 | colors?: Partial<Record<logging.LogLevel, (s: string) => string>>, |
| 26 | ): logging.Logger { |
| 27 | const logger = new logging.IndentLogger('cling'); |
| 28 | |
| 29 | logger.pipe(filter((entry) => entry.level !== 'debug' || verbose)).subscribe((entry) => { |
| 30 | const color = colors && colors[entry.level]; |
| 31 | let output = stdout; |
| 32 | |
| 33 | switch (entry.level) { |
| 34 | case 'warn': |
| 35 | case 'fatal': |
| 36 | case 'error': |
| 37 | output = stderr; |
| 38 | break; |
| 39 | } |
| 40 | |
| 41 | // If we do console.log(message) or process.stdout.write(message + '\n'), the process might |
| 42 | // stop before the whole message is written and the stream is flushed. This happens when |
| 43 | // streams are asynchronous. |
| 44 | // |
| 45 | // NodeJS IO streams are different depending on platform and usage. In POSIX environment, |
| 46 | // for example, they're asynchronous when writing to a pipe, but synchronous when writing |
| 47 | // to a TTY. In windows, it's the other way around. You can verify which is which with |
| 48 | // stream.isTTY and platform, but this is not good enough. |
| 49 | // In the async case, one should wait for the callback before sending more data or |
| 50 | // continuing the process. In our case it would be rather hard to do (but not impossible). |
| 51 | // |
| 52 | // Instead we take the easy way out and simply chunk the message and call the write |
| 53 | // function while the buffer drain itself asynchronously. With a smaller chunk size than |
| 54 | // the buffer, we are mostly certain that it works. In this case, the chunk has been picked |
| 55 | // as half a page size (4096/2 = 2048), minus some bytes for the color formatting. |
| 56 | // On POSIX it seems the buffer is 2 pages (8192), but just to be sure (could be different |
| 57 | // by platform). |
| 58 | // |
| 59 | // For more details, see https://nodejs.org/api/process.html#process_a_note_on_process_i_o |
| 60 | const chunkSize = 2000; // Small chunk. |
| 61 | let message = entry.message; |
| 62 | while (message) { |
| 63 | const chunk = message.slice(0, chunkSize); |
| 64 | message = message.slice(chunkSize); |
| 65 | output.write(color ? color(chunk) : chunk); |
| 66 | } |
| 67 | output.write('\n'); |
| 68 | }); |
| 69 | |
| 70 | return logger; |
| 71 | } |