UNPKG

@best/console-stream

Version:

Best stdout stream wrapper

180 lines 6.59 kB
"use strict"; /* * Copyright (c) 2019, salesforce.com, inc. * All rights reserved. * SPDX-License-Identifier: MIT * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const utils_1 = require("@best/utils"); const chalk_1 = __importDefault(require("chalk")); const trim_path_1 = __importDefault(require("./utils/trim-path")); const count_eod_1 = __importDefault(require("./utils/count-eod")); const proxy_stream_1 = require("./utils/proxy-stream"); var State; (function (State) { State["QUEUED"] = "QUEUED"; State["BUILDING"] = "BUILDING"; State["DONE"] = "DONE"; })(State || (State = {})); const STATE_ANSI = { BUILDING: chalk_1.default.reset.inverse.yellow.bold(` ${State.BUILDING} `), QUEUED: chalk_1.default.reset.inverse.gray.bold(` ${State.QUEUED} `), DONE: chalk_1.default.reset.inverse.green.bold(` ${State.DONE} `), }; const INIT_MSG = '\n Building benchmarks... \n\n'; function printState(state) { return STATE_ANSI[state]; } function printDisplayName(displayPath, overflow) { const dirname = overflow ? (0, trim_path_1.default)(path_1.default.dirname(displayPath), overflow) : path_1.default.dirname(displayPath); const basename = path_1.default.basename(displayPath); return chalk_1.default.dim(dirname + path_1.default.sep) + chalk_1.default.bold(basename); } function printProjectName(projectName) { return ' ' + chalk_1.default.reset.cyan.dim(`(${projectName})`); } class BuildOutputStream { stdoutColumns; stdoutWrite; isInteractive; _streamBuffer = ''; _state; _innerLog = ''; _scheduled = null; _proxiedStream; constructor(buildConfig, stream, isInteractive) { this.stdoutColumns = stream.columns || 80; this.stdoutWrite = stream.write.bind(stream); this.isInteractive = isInteractive !== undefined ? isInteractive : utils_1.isInteractive; this._state = this.initState(buildConfig); this._proxiedStream = (0, proxy_stream_1.proxyStream)(stream, this.isInteractive); } initState(buildConfig) { return buildConfig.reduce((state, { matches, config: { rootDir, projectName } }) => { matches.forEach((benchmarkAbsPath) => { state.set(benchmarkAbsPath, { projectName, state: State.QUEUED, displayPath: path_1.default.relative(rootDir, benchmarkAbsPath), }); }); return state; }, new Map()); } clearBufferStream() { let buffer = this._streamBuffer; const lines = (0, count_eod_1.default)(buffer); if (lines) { buffer = '\r\x1B[K\r\x1B[1A'.repeat(lines); } if (this.isInteractive) { // clear last line this.stdoutWrite('\x1b[999D\x1b[K'); } this.stdoutWrite(buffer); this._streamBuffer = ''; } writeBufferStream(str) { this._streamBuffer += str; this.stdoutWrite(str); } updateBenchmarkState(benchmarkPath, state) { const stateConfig = this._state.get(benchmarkPath); if (!stateConfig) { throw new Error(`Unknown benchmark build started (${benchmarkPath})`); } stateConfig.state = state; } onBenchmarkBuildStart(benchmarkPath) { this.updateBenchmarkState(benchmarkPath, State.BUILDING); if (this.isInteractive) { this.scheduleUpdate(); } else { const benchmarkState = this._state.get(benchmarkPath); if (benchmarkState) { this.stdoutWrite(this.printBenchmark(benchmarkState)); } } } scheduleUpdate() { if (!this._scheduled) { this._scheduled = setTimeout(() => { this.updateStream(); this._scheduled = null; }, 10); } } printBenchmark({ state, projectName, displayPath }, streamProxyBuffer) { const columns = this.stdoutColumns; const overflow = columns - (state.length + projectName.length + displayPath.length + /* for padding */ 14); const hasOverflow = overflow < 0; const ansiState = printState(state); const ansiProjectName = printProjectName(projectName); const ansiDisplayname = printDisplayName(displayPath, hasOverflow ? Math.abs(overflow) : 0); const proxiedBuffer = streamProxyBuffer ? `Buffered console logs:\n ${streamProxyBuffer}` : ''; return `${ansiState} ${ansiProjectName} ${ansiDisplayname}\n${proxiedBuffer}`; } updateStream() { const innerState = this._innerLog; let buffer = INIT_MSG; for (const { state, displayPath, projectName } of this._state.values()) { buffer += this.printBenchmark({ state, displayPath, projectName }, this._proxiedStream.readBuffer()); } if (innerState) { buffer += `\n${innerState}\n`; } this.clearBufferStream(); this.writeBufferStream(buffer); } onBenchmarkBuildEnd(benchmarkPath) { this.updateBenchmarkState(benchmarkPath, State.DONE); this._innerLog = ''; if (this.isInteractive) { this.scheduleUpdate(); } else { const benchmarkState = this._state.get(benchmarkPath); if (benchmarkState) { this.stdoutWrite(this.printBenchmark(benchmarkState, this._proxiedStream.readBuffer()) + '\n'); } } } log(message) { this._innerLog = message; if (this.isInteractive) { this.scheduleUpdate(); } else { this.stdoutWrite(` :: ${message}\n`); } } init() { if (this.isInteractive) { this.updateStream(); } else { this.stdoutWrite(INIT_MSG); } } finish() { this._proxiedStream.unproxyStream(); if (this._scheduled) { clearTimeout(this._scheduled); this._scheduled = null; } if (this.isInteractive) { this.updateStream(); } else { this.stdoutWrite('\n'); } } } exports.default = BuildOutputStream; //# sourceMappingURL=build-stream.js.map