UNPKG

zcatalyst-cli

Version:

Command Line Tool for CATALYST

218 lines (217 loc) 8.63 kB
'use strict'; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const ansi_colors_1 = __importDefault(require("ansi-colors")); const cli_cursor_1 = __importDefault(require("cli-cursor")); const readline_1 = require("readline"); const strip_ansi_1 = __importDefault(require("strip-ansi")); const index_1 = __importDefault(require("../error/index")); const utils_js_1 = require("../util_modules/logger/utils.js"); const shell_js_1 = require("../util_modules/shell.js"); const spinners_json_1 = require("./spinners.json"); const utils_1 = require("./utils"); const logger_1 = require("../util_modules/logger"); const env_1 = require("../util_modules/env"); class Throbber { constructor(options) { this.options = options; this.spinners = {}; this.isCursorHidden = false; this.currentInterval = null; this.stream = env_1.isVsCode ? logger_1.LogStreamFactory.getStream() : process.stderr; this.lineCount = 0; this.currentFrameIndex = 0; this.spin = !this.options.disableSpins && !process.env.CI && ((process.stderr && process.stderr.isTTY) || env_1.isVsCode); this.bindSigint(); Throbber.instance = this; } static getInstance(options = {}) { if (Throbber.instance !== undefined) { return Throbber.instance; } const instance = new Throbber(Object.assign({ spinnerColor: 'cyanBright', spinner: (0, shell_js_1.supportsUnicode)() ? spinners_json_1.dots : spinners_json_1.dashes, disableSpins: false, status: 'spinning', succeedPrefix: utils_js_1.CHAR.success, failPrefix: utils_js_1.CHAR.error }, options)); Throbber.instance = instance; return instance; } pick(name) { return this.spinners[name]; } add(name, options = {}) { if (!options.text) { options.text = name; } const spinnerProperties = Object.assign(Object.assign({}, this.options), options); if (this.spin) { this.spinners[name] = spinnerProperties; } this.updateSpinnerState(); return spinnerProperties; } update(name, options = {}) { const { status } = options; this.setSpinnerProperties(name, options, status); this.updateSpinnerState(); return this.spinners[name]; } succeed(name, options = {}) { this.setSpinnerProperties(name, options, 'succeed'); this.updateSpinnerState(); return this.spinners[name]; } fail(name, options = {}) { this.setSpinnerProperties(name, options, 'fail'); this.updateSpinnerState(); return this.spinners[name]; } remove(name) { const spinner = this.spinners[name]; delete this.spinners[name]; this.checkIfActiveSpinners(); return spinner; } stopAll(newStatus = 'stopped') { Object.keys(this.spinners).forEach((name) => { const { status: currentStatus } = this.spinners[name]; if (currentStatus !== 'fail' && currentStatus !== 'succeed' && currentStatus !== 'non-spinnable') { if (newStatus === 'succeed' || newStatus === 'fail') { this.spinners[name].status = newStatus; this.spinners[name].color = newStatus === 'succeed' ? this.options.succeedColor : this.options.failColor; } else { this.spinners[name].status = 'stopped'; this.spinners[name].color = 'grey'; } } }); this.checkIfActiveSpinners(); return this.spinners; } hasActiveSpinners() { return !!Object.values(this.spinners).find(({ status }) => status === 'spinning'); } setSpinnerProperties(name, options, status = 'spinning') { if (!this.spin) { return; } if (!this.spinners[name]) { throw new index_1.default(`No spinner initialized with name ${name}`); } status = status || 'spinning'; this.spinners[name] = Object.assign(Object.assign(Object.assign({}, this.spinners[name]), options), { status }); } updateSpinnerState() { if (this.spin) { if (this.currentInterval !== null) { clearInterval(this.currentInterval); } this.currentInterval = this.loopStream(); if (!this.isCursorHidden) { cli_cursor_1.default.hide(); } this.isCursorHidden = true; this.checkIfActiveSpinners(); } else { this.setRawStreamOutput(); } } loopStream() { if (this.options.spinner === undefined) { throw new index_1.default('LoopStream must be called only with valid spinner object', { exit: 2 }); } const { frames, interval } = this.options.spinner; return setInterval(() => { this.setStreamOutput(frames[this.currentFrameIndex]); this.currentFrameIndex = this.currentFrameIndex === frames.length - 1 ? 0 : ++this.currentFrameIndex; }, interval); } setStreamOutput(frame = '') { let output = ''; const linesLength = []; const hasActiveSpinners = this.hasActiveSpinners(); Object.values(this.spinners).map(({ text, status, color, spinnerColor, succeedPrefix, failPrefix, indent }) => { text = text === undefined ? '' : text; let line; let prefixLength = indent || 0; if (status === 'spinning') { prefixLength += frame.length + 1; text = (0, utils_1.breakText)(text, prefixLength); line = `${ansi_colors_1.default[spinnerColor](frame)} ${color ? ansi_colors_1.default[color](text) : text}`; } else { if (status === 'succeed') { prefixLength += (0, strip_ansi_1.default)(succeedPrefix).length + 1; if (hasActiveSpinners) { text = (0, utils_1.breakText)(text, prefixLength); } line = `${succeedPrefix} ${text}`; } else if (status === 'fail') { prefixLength += (0, strip_ansi_1.default)(failPrefix).length + 1; if (hasActiveSpinners) { text = (0, utils_1.breakText)(text, prefixLength); } line = `${failPrefix} ${text}`; } else { if (hasActiveSpinners) { text = (0, utils_1.breakText)(text, prefixLength); } line = color ? ansi_colors_1.default[color](text) : text; } } linesLength.push(...(0, utils_1.getLinesLength)(text, prefixLength)); output += indent ? `${' '.repeat(indent)}${line}\n` : `${line}\n`; }); if (!hasActiveSpinners) { (0, readline_1.clearScreenDown)(this.stream); } (0, utils_1.writeStream)(this.stream, output, linesLength); if (hasActiveSpinners) { (0, utils_1.cleanStream)(this.stream, linesLength); } this.lineCount = linesLength.length; } setRawStreamOutput() { Object.values(this.spinners).forEach((i) => { process.stderr.write(`- ${i.text}\n`); }); } checkIfActiveSpinners() { if (!this.hasActiveSpinners()) { if (this.spin) { this.setStreamOutput(); (0, readline_1.moveCursor)(this.stream, 0, this.lineCount); if (this.currentInterval !== null) { clearInterval(this.currentInterval); } this.isCursorHidden = false; cli_cursor_1.default.show(); } this.spinners = {}; } } bindSigint() { process.prependOnceListener('SIGINT', () => { if (!this.hasActiveSpinners()) { return; } cli_cursor_1.default.show(); (0, readline_1.moveCursor)(process.stderr, 0, this.lineCount); }); } } exports.default = Throbber;