@log4brains/cli-common
Version:
Log4brains architecture knowledge base common CLI features
295 lines (236 loc) • 7.45 kB
JavaScript
import chalk from 'chalk';
import inquirer from 'inquirer';
import ora from 'ora';
import CliTable3 from 'cli-table3';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-console */
/**
* Captures console.log(), console.error() and console.warn()
* Source: https://github.com/vercel/next.js/blob/canary/packages/next/build/spinner.ts Thanks!
*/
class ConsoleCapturer {
start() {
this.origConsoleLog = console.log;
this.origConsoleWarn = console.warn;
this.origConsoleError = console.error;
const logHandle = (method, args) => {
if (this.onLog) {
this.onLog(method, args, method === this.origConsoleLog ? "stdout" : "stderr");
}
};
console.log = (...args) => logHandle(this.origConsoleLog, args);
console.warn = (...args) => logHandle(this.origConsoleWarn, args);
console.error = (...args) => logHandle(this.origConsoleError, args);
}
doPrintln(message, ...optionalParams) {
if (!this.origConsoleLog) {
throw new Error("ConsoleCapturer is not started");
}
this.origConsoleLog(message != null ? message : "", ...optionalParams);
}
doPrintlnErr(message, ...optionalParams) {
if (!this.origConsoleError) {
throw new Error("ConsoleCapturer is not started");
}
this.origConsoleError(message != null ? message : "", ...optionalParams);
}
stop() {
if (!this.origConsoleLog || !this.origConsoleWarn || !this.origConsoleError) {
throw new Error("ConsoleCapturer is not started");
}
console.log = this.origConsoleLog;
console.warn = this.origConsoleWarn;
console.error = this.origConsoleError;
this.origConsoleLog = undefined;
this.origConsoleWarn = undefined;
this.origConsoleError = undefined;
}
}
class AppConsole {
constructor(opts = {}) {
this.spinnerConsoleCapturer = new ConsoleCapturer();
this.opts = _extends({
debug: false,
traces: false
}, opts);
}
isSpinning() {
return !!this.spinner;
}
startSpinner(message) {
if (this.spinner) {
throw new Error("Spinner already started");
}
this.spinner = ora({
text: message,
spinner: "bouncingBar",
stream: process.stdout
}).start(); // Add capturing of console.log/warn/error to allow pausing
// the spinner before logging and then restarting spinner after
this.spinnerConsoleCapturer.onLog = (method, args) => {
var _this$spinner, _this$spinner2;
(_this$spinner = this.spinner) == null ? void 0 : _this$spinner.stop();
method(...args);
(_this$spinner2 = this.spinner) == null ? void 0 : _this$spinner2.start();
};
this.spinnerConsoleCapturer.start();
}
updateSpinner(message) {
if (!this.spinner) {
throw new Error("Spinner is not started");
}
this.spinner.text = message;
}
stopSpinner(withError = false) {
if (!this.spinner) {
throw new Error("Spinner is not started");
}
this.spinnerConsoleCapturer.stop();
this.spinner.stopAndPersist({
symbol: chalk.dim(withError ? "[== ]" : "[====]"),
text: `${this.spinner.text} ${withError ? chalk.red("Error") : "Done"}`
});
this.println();
this.spinner = undefined;
}
println(message, ...optionalParams) {
console.log(message != null ? message : "", ...optionalParams);
}
printlnErr(message, ...optionalParams) {
console.error(message != null ? message : "", ...optionalParams);
}
debug(message, ...optionalParams) {
if (this.opts.debug) {
this.println(chalk.dim(message), ...optionalParams.map(p => chalk.dim(p)));
}
}
warn(messageOrErr) {
if (messageOrErr instanceof Error) {
this.printlnErr(chalk.yellowBright(` ⚠ ${messageOrErr.message}`));
if (this.opts.traces && messageOrErr.stack) {
this.printlnErr(chalk.yellow(messageOrErr.stack));
this.printlnErr();
}
} else {
this.printlnErr(chalk.yellowBright(` ⚠ ${messageOrErr}`));
}
}
error(messageOrErr) {
if (messageOrErr instanceof Error) {
this.printlnErr(chalk.redBright(` ✖ ${messageOrErr.message}`));
if (this.opts.traces && messageOrErr.stack) {
this.printlnErr(chalk.red(messageOrErr.stack));
this.printlnErr();
}
} else {
this.printlnErr(chalk.redBright(` ✖ ${messageOrErr}`));
}
}
fatal(messageOrErr) {
this.printlnErr();
if (messageOrErr instanceof Error) {
this.printlnErr(`${chalk.bgRed.bold(" FATAL ")} ${chalk.redBright(messageOrErr.message)}`);
if (this.opts.traces && messageOrErr.stack) {
this.printlnErr();
this.printlnErr(chalk.red(messageOrErr.stack));
}
} else {
this.printlnErr(`${chalk.bgRed.bold(" FATAL ")} ${chalk.redBright(messageOrErr)}`);
}
this.printlnErr();
}
success(message) {
this.println(chalk.greenBright(` ✔ ${message}`));
}
createTable(options) {
return new CliTable3(_extends({
style: {
head: ["blue"]
}
}, options));
}
printTable(table, raw = false) {
if (raw) {
table.forEach(value => {
if (typeof value === "object" && value instanceof Array) {
console.log(value.join(","));
} else {
console.log(value);
}
});
} else {
console.log(table.toString());
}
}
async askYesNoQuestion(question, defaultValue) {
console.log("");
const answer = await inquirer.prompt([{
type: "confirm",
name: "q",
message: question,
default: defaultValue
}]);
return answer.q;
}
async askInputQuestion(question, defaultValue) {
console.log("");
const answer = await inquirer.prompt([{
type: "input",
name: "q",
message: question,
default: defaultValue
}]);
return answer.q;
}
async askInputQuestionAndValidate(question, validationCb, defaultValue) {
let answer;
let valid = true;
let i = 0;
do {
if (valid !== true) {
console.log(chalk.red(`✗ Please enter a correct value${valid === false ? "" : `: ${valid}`}`));
}
if (i >= 10) {
throw new Error("Reached maximum number of retries (10)");
} // eslint-disable-next-line no-await-in-loop
answer = await this.askInputQuestion(question, defaultValue);
valid = validationCb(answer);
i += 1;
} while (valid !== true);
return answer;
}
async askListQuestion(question, choices, defaultValue) {
console.log("");
const answer = await inquirer.prompt([{
type: "list",
name: "q",
message: question,
default: defaultValue,
choices
}]);
return answer.q;
}
}
class FailureExit extends Error {
constructor() {
super("The CLI exited with an error");
}
}
export { AppConsole, ConsoleCapturer, FailureExit };
//# sourceMappingURL=index.module.js.map