|
- // src/listr.ts
- import pMap from "p-map";
- import { Subject as Subject2 } from "rxjs";
-
- // src/constants/state.constants.ts
- var ListrTaskState = /* @__PURE__ */ ((ListrTaskState2) => {
- ListrTaskState2["PENDING"] = "PENDING";
- ListrTaskState2["COMPLETED"] = "COMPLETED";
- ListrTaskState2["FAILED"] = "FAILED";
- ListrTaskState2["SKIPPED"] = "SKIPPED";
- ListrTaskState2["ROLLING_BACK"] = "ROLLING_BACK";
- ListrTaskState2["ROLLED_BACK"] = "ROLLED_BACK";
- ListrTaskState2["RETRY"] = "RETRY";
- return ListrTaskState2;
- })(ListrTaskState || {});
-
- // src/lib/task.ts
- import { isObservable, Subject } from "rxjs";
- import { Readable } from "stream";
-
- // src/constants/event.constants.ts
- var ListrEventType = /* @__PURE__ */ ((ListrEventType2) => {
- ListrEventType2["TITLE"] = "TITLE";
- ListrEventType2["STATE"] = "STATE";
- ListrEventType2["ENABLED"] = "ENABLED";
- ListrEventType2["SUBTASK"] = "SUBTASK";
- ListrEventType2["DATA"] = "DATA";
- ListrEventType2["MESSAGE"] = "MESSAGE";
- return ListrEventType2;
- })(ListrEventType || {});
-
- // src/utils/general.ts
- import rfdc from "rfdc";
- var clone = rfdc({ circles: true });
- function cloneObject(obj) {
- return clone(obj);
- }
-
- // src/interfaces/listr-error.interface.ts
- var ListrError = class extends Error {
- constructor(error, type, task) {
- super(error.message);
- this.error = error;
- this.type = type;
- this.task = task;
- this.name = "ListrError";
- this.path = [...task.listr.path ?? [], task.title].join(" > ");
- if ((task == null ? void 0 : task.options.collectErrors) === "full") {
- this.task = cloneObject(task);
- this.ctx = cloneObject(task.listr.ctx);
- }
- this.stack = error == null ? void 0 : error.stack;
- }
- };
- var ListrErrorTypes = /* @__PURE__ */ ((ListrErrorTypes2) => {
- ListrErrorTypes2["WILL_RETRY"] = "WILL_RETRY";
- ListrErrorTypes2["WILL_ROLLBACK"] = "WILL_ROLLBACK";
- ListrErrorTypes2["HAS_FAILED_TO_ROLLBACK"] = "HAS_FAILED_TO_ROLLBACK";
- ListrErrorTypes2["HAS_FAILED"] = "HAS_FAILED";
- ListrErrorTypes2["HAS_FAILED_WITHOUT_ERROR"] = "HAS_FAILED_WITHOUT_ERROR";
- return ListrErrorTypes2;
- })(ListrErrorTypes || {});
- var PromptError = class extends Error {
- constructor(message) {
- super(message);
- this.name = "PromptError";
- }
- };
-
- // src/utils/assert.ts
- function assertFunctionOrSelf(functionOrSelf, ...args) {
- if (typeof functionOrSelf === "function") {
- return functionOrSelf(...args);
- } else {
- return functionOrSelf;
- }
- }
-
- // src/renderer/default.renderer.ts
- import cliTruncate from "cli-truncate";
- import logUpdate from "log-update";
- import { EOL } from "os";
- import cliWrap from "wrap-ansi";
-
- // src/utils/colorette.ts
- import { createColors } from "colorette";
- var _a;
- var colorette_default = createColors({ useColor: ((_a = process.env) == null ? void 0 : _a.LISTR_DISABLE_COLOR) !== "1" });
-
- // src/utils/is-unicode-supported.ts
- function isUnicodeSupported() {
- if (process.platform !== "win32") {
- return true;
- }
- return Boolean(process.env.CI) || Boolean(process.env.WT_SESSION) || process.env.TERM_PROGRAM === "vscode" || process.env.TERM === "xterm-256color" || process.env.TERM === "alacritty";
- }
-
- // src/utils/figures.ts
- var FIGURES_MAIN = {
- warning: "\u26A0",
- cross: "\u2716",
- arrowDown: "\u2193",
- tick: "\u2714",
- arrowRight: "\u2192",
- pointer: "\u276F",
- checkboxOn: "\u2612",
- arrowLeft: "\u2190",
- squareSmallFilled: "\u25FC",
- pointerSmall: "\u203A"
- };
- var FIGURES_FALLBACK = {
- ...FIGURES_MAIN,
- warning: "\u203C",
- cross: "\xD7",
- tick: "\u221A",
- pointer: ">",
- checkboxOn: "[\xD7]",
- squareSmallFilled: "\u25A0"
- };
- var figures = isUnicodeSupported() ? FIGURES_MAIN : FIGURES_FALLBACK;
-
- // src/utils/indent-string.ts
- function indentString(string, count) {
- return string.replace(/^(?!\s*$)/gm, " ".repeat(count));
- }
-
- // src/utils/parse-time.ts
- function parseTaskTime(duration) {
- const seconds = Math.floor(duration / 1e3);
- const minutes = Math.floor(seconds / 60);
- let parsedTime;
- if (seconds === 0 && minutes === 0) {
- parsedTime = `0.${Math.floor(duration / 100)}s`;
- }
- if (seconds > 0) {
- parsedTime = `${seconds % 60}s`;
- }
- if (minutes > 0) {
- parsedTime = `${minutes}m${parsedTime}`;
- }
- return parsedTime;
- }
-
- // src/renderer/default.renderer.ts
- var _DefaultRenderer = class {
- constructor(tasks, options, renderHook$) {
- this.tasks = tasks;
- this.options = options;
- this.renderHook$ = renderHook$;
- this.bottomBar = {};
- this.spinner = !isUnicodeSupported() ? ["-", "\\", "|", "/"] : ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
- this.spinnerPosition = 0;
- this.options = { ..._DefaultRenderer.rendererOptions, ...this.options };
- }
- getTaskOptions(task) {
- return { ..._DefaultRenderer.rendererTaskOptions, ...task.rendererTaskOptions };
- }
- isBottomBar(task) {
- const bottomBar = this.getTaskOptions(task).bottomBar;
- return typeof bottomBar === "number" && bottomBar !== 0 || typeof bottomBar === "boolean" && bottomBar !== false;
- }
- hasPersistentOutput(task) {
- return this.getTaskOptions(task).persistentOutput === true;
- }
- hasTimer(task) {
- return this.getTaskOptions(task).showTimer === true;
- }
- getSelfOrParentOption(task, key) {
- var _a2, _b;
- return ((_a2 = task == null ? void 0 : task.rendererOptions) == null ? void 0 : _a2[key]) ?? ((_b = this.options) == null ? void 0 : _b[key]);
- }
- getTaskTime(task) {
- return colorette_default.dim(`[${parseTaskTime(task.message.duration)}]`);
- }
- createRender(options) {
- options = {
- ...{
- tasks: true,
- bottomBar: true,
- prompt: true
- },
- ...options
- };
- const render = [];
- const renderTasks = this.multiLineRenderer(this.tasks);
- const renderBottomBar = this.renderBottomBar();
- const renderPrompt = this.renderPrompt();
- if (options.tasks && (renderTasks == null ? void 0 : renderTasks.trim().length) > 0) {
- render.push(renderTasks);
- }
- if (options.bottomBar && (renderBottomBar == null ? void 0 : renderBottomBar.trim().length) > 0) {
- render.push((render.length > 0 ? EOL : "") + renderBottomBar);
- }
- if (options.prompt && (renderPrompt == null ? void 0 : renderPrompt.trim().length) > 0) {
- render.push((render.length > 0 ? EOL : "") + renderPrompt);
- }
- return render.length > 0 ? render.join(EOL) : "";
- }
- render() {
- var _a2;
- if (this.id) {
- return;
- }
- const updateRender = () => logUpdate(this.createRender());
- if (!((_a2 = this.options) == null ? void 0 : _a2.lazy)) {
- this.id = setInterval(() => {
- this.spinnerPosition = ++this.spinnerPosition % this.spinner.length;
- updateRender();
- }, 100);
- }
- this.renderHook$.subscribe(() => {
- updateRender();
- });
- }
- end() {
- clearInterval(this.id);
- if (this.id) {
- this.id = void 0;
- }
- logUpdate.clear();
- logUpdate.done();
- if (!this.options.clearOutput) {
- process.stdout.write(this.createRender({ prompt: false }) + EOL);
- }
- }
- multiLineRenderer(tasks, level = 0) {
- var _a2, _b;
- let output = [];
- for (const task of tasks) {
- if (task.isEnabled()) {
- if (task.hasTitle()) {
- if (!(tasks.some((task2) => task2.hasFailed()) && !task.hasFailed() && task.options.exitOnError !== false && !(task.isCompleted() || task.isSkipped()))) {
- if (task.hasFailed() && this.getSelfOrParentOption(task, "collapseErrors")) {
- output = [
- ...output,
- this.formatString(
- !task.hasSubtasks() && task.message.error && this.getSelfOrParentOption(task, "showErrorMessage") ? task.message.error : task.title,
- this.getSymbol(task),
- level
- )
- ];
- } else if (task.isSkipped() && this.getSelfOrParentOption(task, "collapseSkips")) {
- output = [
- ...output,
- this.formatString(
- this.addSuffixToMessage(
- task.message.skip && this.getSelfOrParentOption(task, "showSkipMessage") ? task.message.skip : task.title,
- "SKIPPED",
- this.getSelfOrParentOption(task, "suffixSkips")
- ),
- this.getSymbol(task),
- level
- )
- ];
- } else if (task.isRetrying() && this.getSelfOrParentOption(task, "suffixRetries")) {
- output = [...output, this.formatString(this.addSuffixToMessage(task.title, `RETRYING-${task.message.retry.count}`), this.getSymbol(task), level)];
- } else if (task.isCompleted() && task.hasTitle() && (this.getSelfOrParentOption(task, "showTimer") || this.hasTimer(task))) {
- output = [...output, this.formatString(`${task == null ? void 0 : task.title} ${this.getTaskTime(task)}`, this.getSymbol(task), level)];
- } else {
- output = [...output, this.formatString(task.title, this.getSymbol(task), level)];
- }
- } else {
- output = [...output, this.formatString(task.title, colorette_default.red(figures.squareSmallFilled), level)];
- }
- }
- if (!task.hasSubtasks() || !this.getSelfOrParentOption(task, "showSubtasks")) {
- if (task.hasFailed() && this.getSelfOrParentOption(task, "collapseErrors") === false && (this.getSelfOrParentOption(task, "showErrorMessage") || !this.getSelfOrParentOption(task, "showSubtasks"))) {
- output = [...output, this.dumpData(task, level, "error")];
- } else if (task.isSkipped() && this.getSelfOrParentOption(task, "collapseSkips") === false && (this.getSelfOrParentOption(task, "showSkipMessage") || !this.getSelfOrParentOption(task, "showSubtasks"))) {
- output = [...output, this.dumpData(task, level, "skip")];
- }
- }
- if (task == null ? void 0 : task.output) {
- if ((task.isPending() || task.isRetrying() || task.isRollingBack()) && task.isPrompt()) {
- this.promptBar = task.output;
- } else if (this.isBottomBar(task) || !task.hasTitle()) {
- const data = [this.dumpData(task, -1)];
- if (!this.bottomBar[task.id]) {
- this.bottomBar[task.id] = {};
- this.bottomBar[task.id].data = [];
- const bottomBar = this.getTaskOptions(task).bottomBar;
- if (typeof bottomBar === "boolean") {
- this.bottomBar[task.id].items = 1;
- } else {
- this.bottomBar[task.id].items = bottomBar;
- }
- }
- if (!((_b = (_a2 = this.bottomBar[task.id]) == null ? void 0 : _a2.data) == null ? void 0 : _b.some((element) => data.includes(element))) && !task.isSkipped()) {
- this.bottomBar[task.id].data = [...this.bottomBar[task.id].data, ...data];
- }
- } else if (task.isPending() || task.isRetrying() || task.isRollingBack() || this.hasPersistentOutput(task)) {
- output = [...output, this.dumpData(task, level)];
- }
- }
- if (this.getSelfOrParentOption(task, "showSubtasks") !== false && task.hasSubtasks() && (task.isPending() || task.hasFailed() || task.isCompleted() && !task.hasTitle() || task.isCompleted() && this.getSelfOrParentOption(task, "collapse") === false && !task.subtasks.some((subtask) => subtask.rendererOptions.collapse === true) || task.subtasks.some((subtask) => subtask.rendererOptions.collapse === false) || task.subtasks.some((subtask) => subtask.hasFailed()) || task.subtasks.some((subtask) => subtask.hasRolledBack()))) {
- const subtaskLevel = !task.hasTitle() ? level : level + 1;
- const subtaskRender = this.multiLineRenderer(task.subtasks, subtaskLevel);
- if ((subtaskRender == null ? void 0 : subtaskRender.trim()) !== "") {
- output = [...output, subtaskRender];
- }
- }
- if (task.isCompleted() || task.hasFailed() || task.isSkipped() || task.hasRolledBack()) {
- this.promptBar = null;
- if (!this.hasPersistentOutput(task)) {
- delete this.bottomBar[task.id];
- }
- }
- }
- }
- output = output.filter(Boolean);
- if (output.length > 0) {
- return output.join(EOL);
- } else {
- return;
- }
- }
- renderBottomBar() {
- if (Object.keys(this.bottomBar).length > 0) {
- this.bottomBar = Object.keys(this.bottomBar).reduce((o, key) => {
- if (!(o == null ? void 0 : o[key])) {
- o[key] = {};
- }
- o[key] = this.bottomBar[key];
- this.bottomBar[key].data = this.bottomBar[key].data.slice(-this.bottomBar[key].items);
- o[key].data = this.bottomBar[key].data;
- return o;
- }, {});
- return Object.values(this.bottomBar).reduce((o, value) => o = [...o, ...value.data], []).filter(Boolean).join(EOL);
- }
- }
- renderPrompt() {
- if (this.promptBar) {
- return this.promptBar;
- }
- }
- dumpData(task, level, source = "output") {
- let data;
- switch (source) {
- case "output":
- data = task.output;
- break;
- case "skip":
- data = task.message.skip;
- break;
- case "error":
- data = task.message.error;
- break;
- }
- if (task.hasTitle() && source === "error" && data === task.title) {
- return;
- }
- if (typeof data === "string") {
- return this.formatString(data, this.getSymbol(task, true), level + 1);
- }
- }
- formatString(str, icon, level) {
- if (str.trim() === "") {
- return;
- }
- str = `${icon} ${str}`;
- let parsedStr;
- let columns = process.stdout.columns ? process.stdout.columns : 80;
- columns = columns - level * this.options.indentation - 2;
- switch (this.options.formatOutput) {
- case "truncate":
- parsedStr = str.split(EOL).map((s, i) => {
- return cliTruncate(this.indentMultilineOutput(s, i), columns);
- });
- break;
- case "wrap":
- parsedStr = cliWrap(str, columns, { hard: true }).split(EOL).map((s, i) => this.indentMultilineOutput(s, i));
- break;
- default:
- throw new Error("Format option for the renderer is wrong.");
- }
- if (this.options.removeEmptyLines) {
- parsedStr = parsedStr.filter(Boolean);
- }
- return indentString(parsedStr.join(EOL), level * this.options.indentation);
- }
- indentMultilineOutput(str, i) {
- return i > 0 ? indentString(str.trim(), 2) : str.trim();
- }
- getSymbol(task, data = false) {
- var _a2, _b, _c;
- if (task.isPending() && !data) {
- return ((_a2 = this.options) == null ? void 0 : _a2.lazy) || this.getSelfOrParentOption(task, "showSubtasks") !== false && task.hasSubtasks() && !task.subtasks.every((subtask) => !subtask.hasTitle()) ? colorette_default.yellow(figures.pointer) : colorette_default.yellowBright(this.spinner[this.spinnerPosition]);
- } else if (task.isCompleted() && !data) {
- return task.hasSubtasks() && task.subtasks.some((subtask) => subtask.hasFailed()) ? colorette_default.yellow(figures.warning) : colorette_default.green(figures.tick);
- } else if (task.isRetrying() && !data) {
- return ((_b = this.options) == null ? void 0 : _b.lazy) ? colorette_default.yellow(figures.warning) : colorette_default.yellow(this.spinner[this.spinnerPosition]);
- } else if (task.isRollingBack() && !data) {
- return ((_c = this.options) == null ? void 0 : _c.lazy) ? colorette_default.red(figures.warning) : colorette_default.red(this.spinner[this.spinnerPosition]);
- } else if (task.hasRolledBack() && !data) {
- return colorette_default.red(figures.arrowLeft);
- } else if (task.hasFailed() && !data) {
- return task.hasSubtasks() ? colorette_default.red(figures.pointer) : colorette_default.red(figures.cross);
- } else if (task.isSkipped() && !data && this.getSelfOrParentOption(task, "collapseSkips") === false) {
- return colorette_default.yellow(figures.warning);
- } else if (task.isSkipped() && (data || this.getSelfOrParentOption(task, "collapseSkips"))) {
- return colorette_default.yellow(figures.arrowDown);
- }
- return !data ? colorette_default.dim(figures.squareSmallFilled) : figures.pointerSmall;
- }
- addSuffixToMessage(message, suffix, condition) {
- return condition ?? true ? message + colorette_default.dim(` [${suffix}]`) : message;
- }
- };
- var DefaultRenderer = _DefaultRenderer;
- DefaultRenderer.nonTTY = false;
- DefaultRenderer.rendererOptions = {
- indentation: 2,
- clearOutput: false,
- showSubtasks: true,
- collapse: true,
- collapseSkips: true,
- showSkipMessage: true,
- suffixSkips: true,
- collapseErrors: true,
- showErrorMessage: true,
- suffixRetries: true,
- lazy: false,
- showTimer: false,
- removeEmptyLines: true,
- formatOutput: "truncate"
- };
-
- // src/renderer/silent.renderer.ts
- var SilentRenderer = class {
- constructor(tasks, options) {
- this.tasks = tasks;
- this.options = options;
- }
- render() {
- }
- end() {
- }
- };
- SilentRenderer.nonTTY = true;
-
- // src/renderer/simple.renderer.ts
- import { stderr as logUpdate2 } from "log-update";
- import { EOL as EOL2 } from "os";
- var _SimpleRenderer = class {
- constructor(tasks, options) {
- this.tasks = tasks;
- this.options = options;
- this.eventTypeRendererMap = {
- ["SUBTASK" /* SUBTASK */]: (task) => {
- if (task.hasTitle()) {
- this.log(`${colorette_default.blue(figures.pointer)} ${task.title}`);
- }
- if (task.hasSubtasks()) {
- this.render(task.subtasks);
- }
- },
- ["STATE" /* STATE */]: (task) => {
- if (task.isCompleted() && task.hasTitle()) {
- this.log(`${colorette_default.green(figures.tick)} ${task.title}`);
- }
- },
- ["DATA" /* DATA */]: (task, event) => {
- if (task.isPrompt() && !String(event.data).match(/^\n$/)) {
- logUpdate2(`${event.data}`);
- } else {
- this.log(`${figures.pointerSmall} ${event.data}`);
- }
- },
- ["MESSAGE" /* MESSAGE */]: (task, event) => {
- if (event.data.error) {
- const title = _SimpleRenderer.formatTitle(task);
- this.log(`${colorette_default.red(figures.cross)}${title}: ${event.data.error}`);
- } else if (event.data.skip) {
- const title = _SimpleRenderer.formatTitle(task);
- const skip = task.title !== event.data.skip ? `: ${event.data.skip}` : "";
- this.log(`${colorette_default.yellow(figures.arrowDown)}${title} [${colorette_default.yellow(`skipped${skip}`)}]`);
- } else if (event.data.rollback) {
- const title = _SimpleRenderer.formatTitle(task);
- this.log(`${colorette_default.red(figures.arrowLeft)}${title}: ${event.data.rollback}`);
- } else if (event.data.retry) {
- const title = _SimpleRenderer.formatTitle(task);
- this.log(`[${colorette_default.yellow(`${event.data.retry.count}`)}]${title}`);
- }
- }
- };
- this.options = { ..._SimpleRenderer.rendererOptions, ...options };
- }
- static now() {
- return new Date();
- }
- static formatTitle(task) {
- return (task == null ? void 0 : task.title) ? ` ${task.title}` : "";
- }
- log(output) {
- const logOut = (msg) => {
- process[this.options.output].write(msg.endsWith(EOL2) ? msg : `${msg}${EOL2}`);
- };
- if (!this.options.prefixWithTimestamp) {
- logOut(`${output}`);
- return;
- }
- const now = _SimpleRenderer.now();
- const timestamp = String(now.getHours()).padStart(2, "0") + ":" + String(now.getMinutes()).padStart(2, "0") + ":" + String(now.getSeconds()).padStart(2, "0");
- logOut(`${colorette_default.dim(`[${timestamp}]`)} ${output}`);
- }
- end() {
- }
- render(tasks) {
- if (tasks == null ? void 0 : tasks.length) {
- tasks.forEach((task) => {
- task.subscribe((event) => {
- var _a2, _b;
- (_b = (_a2 = this.eventTypeRendererMap)[event.type]) == null ? void 0 : _b.call(_a2, task, event);
- }, this.log);
- });
- } else {
- this.render(this.tasks);
- }
- }
- };
- var SimpleRenderer = _SimpleRenderer;
- SimpleRenderer.nonTTY = true;
- SimpleRenderer.rendererOptions = { prefixWithTimestamp: false, output: "stdout" };
-
- // src/utils/logger.constants.ts
- var LogLevels = /* @__PURE__ */ ((LogLevels2) => {
- LogLevels2["SILENT"] = "SILENT";
- LogLevels2["FAILED"] = "FAILED";
- LogLevels2["SKIPPED"] = "SKIPPED";
- LogLevels2["SUCCESS"] = "SUCCESS";
- LogLevels2["DATA"] = "DATA";
- LogLevels2["STARTED"] = "STARTED";
- LogLevels2["TITLE"] = "TITLE";
- LogLevels2["RETRY"] = "RETRY";
- LogLevels2["ROLLBACK"] = "ROLLBACK";
- return LogLevels2;
- })(LogLevels || {});
-
- // src/utils/logger.ts
- var Logger = class {
- constructor(options) {
- this.options = options;
- }
- fail(message) {
- message = this.parseMessage("FAILED" /* FAILED */, message);
- console.error(message);
- }
- skip(message) {
- message = this.parseMessage("SKIPPED" /* SKIPPED */, message);
- console.info(message);
- }
- success(message) {
- message = this.parseMessage("SUCCESS" /* SUCCESS */, message);
- console.log(message);
- }
- data(message) {
- message = this.parseMessage("DATA" /* DATA */, message);
- console.info(message);
- }
- start(message) {
- message = this.parseMessage("STARTED" /* STARTED */, message);
- console.log(message);
- }
- title(message) {
- message = this.parseMessage("TITLE" /* TITLE */, message);
- console.info(message);
- }
- retry(message) {
- message = this.parseMessage("RETRY" /* RETRY */, message);
- console.warn(message);
- }
- rollback(message) {
- message = this.parseMessage("ROLLBACK" /* ROLLBACK */, message);
- console.warn(message);
- }
- parseMessage(level, message) {
- let multiLineMessage;
- try {
- multiLineMessage = message.split("\n");
- } catch {
- multiLineMessage = [message];
- }
- multiLineMessage = multiLineMessage.map((msg) => {
- return this.logColoring({
- level,
- message: msg
- });
- });
- message = multiLineMessage.join("\n");
- return message;
- }
- logColoring({ level, message }) {
- var _a2, _b, _c, _d, _e, _f, _g, _h;
- let icon;
- let coloring = (input) => {
- return input;
- };
- switch (level) {
- case "FAILED" /* FAILED */:
- if ((_a2 = this.options) == null ? void 0 : _a2.useIcons) {
- coloring = colorette_default.red;
- icon = figures.cross;
- } else {
- icon = this.wrapInBrackets(level);
- }
- break;
- case "SKIPPED" /* SKIPPED */:
- if ((_b = this.options) == null ? void 0 : _b.useIcons) {
- coloring = colorette_default.yellow;
- icon = figures.arrowDown;
- } else {
- icon = this.wrapInBrackets(level);
- }
- break;
- case "SUCCESS" /* SUCCESS */:
- if ((_c = this.options) == null ? void 0 : _c.useIcons) {
- coloring = colorette_default.green;
- icon = figures.tick;
- } else {
- icon = this.wrapInBrackets(level);
- }
- break;
- case "DATA" /* DATA */:
- if ((_d = this.options) == null ? void 0 : _d.useIcons) {
- icon = figures.arrowRight;
- } else {
- icon = this.wrapInBrackets(level);
- }
- break;
- case "STARTED" /* STARTED */:
- if ((_e = this.options) == null ? void 0 : _e.useIcons) {
- icon = figures.pointer;
- } else {
- icon = this.wrapInBrackets(level);
- }
- break;
- case "TITLE" /* TITLE */:
- if ((_f = this.options) == null ? void 0 : _f.useIcons) {
- icon = figures.checkboxOn;
- } else {
- icon = this.wrapInBrackets(level);
- }
- break;
- case "RETRY" /* RETRY */:
- if ((_g = this.options) == null ? void 0 : _g.useIcons) {
- coloring = colorette_default.yellow;
- icon = figures.pointer;
- } else {
- icon = this.wrapInBrackets(level);
- }
- break;
- case "ROLLBACK" /* ROLLBACK */:
- if ((_h = this.options) == null ? void 0 : _h.useIcons) {
- coloring = colorette_default.red;
- icon = figures.arrowLeft;
- } else {
- icon = this.wrapInBrackets(level);
- }
- break;
- }
- return coloring(`${icon} ${message}`);
- }
- wrapInBrackets(level) {
- return `[${level}]`;
- }
- };
-
- // src/renderer/verbose.renderer.ts
- var _VerboseRenderer = class {
- constructor(tasks, options) {
- this.tasks = tasks;
- this.options = options;
- var _a2, _b, _c, _d;
- if (((_a2 = this.options) == null ? void 0 : _a2.logger) && ((_b = this.options) == null ? void 0 : _b.options)) {
- this.logger = new this.options.logger(this.options.options);
- } else if ((_c = this.options) == null ? void 0 : _c.logger) {
- this.logger = new this.options.logger();
- } else {
- this.logger = new Logger({ useIcons: (_d = this.options) == null ? void 0 : _d.useIcons });
- }
- this.options = { ..._VerboseRenderer.rendererOptions, ...this.options };
- }
- render() {
- this.verboseRenderer(this.tasks);
- }
- end() {
- }
- verboseRenderer(tasks) {
- return tasks == null ? void 0 : tasks.forEach((task) => {
- task.subscribe(
- (event) => {
- var _a2, _b, _c, _d, _e, _f, _g, _h;
- if (task.isEnabled()) {
- const taskTitle = task.hasTitle() ? task.title : "Task without title.";
- if (event.type === "SUBTASK" /* SUBTASK */ && task.hasSubtasks()) {
- this.verboseRenderer(task.subtasks);
- } else if (event.type === "STATE" /* STATE */) {
- if (((_a2 = this.options) == null ? void 0 : _a2.logEmptyTitle) !== false || task.hasTitle()) {
- if (task.isPending()) {
- this.logger.start(taskTitle);
- } else if (task.isCompleted()) {
- this.logger.success(taskTitle + (((_b = this.options) == null ? void 0 : _b.showTimer) && ((_c = task.message) == null ? void 0 : _c.duration) ? ` [${parseTaskTime(task.message.duration)}]` : ""));
- }
- }
- } else if (event.type === "DATA" /* DATA */ && !!event.data) {
- this.logger.data(String(event.data));
- } else if (event.type === "TITLE" /* TITLE */) {
- if (((_d = this.options) == null ? void 0 : _d.logTitleChange) !== false) {
- this.logger.title(String(event.data));
- }
- } else if (event.type === "MESSAGE" /* MESSAGE */) {
- if ((_e = event.data) == null ? void 0 : _e.error) {
- this.logger.fail(String(event.data.error));
- } else if ((_f = event.data) == null ? void 0 : _f.skip) {
- this.logger.skip(String(event.data.skip));
- } else if ((_g = event.data) == null ? void 0 : _g.rollback) {
- this.logger.rollback(String(event.data.rollback));
- } else if ((_h = event.data) == null ? void 0 : _h.retry) {
- this.logger.retry(`[${event.data.retry.count}] ` + String(taskTitle));
- }
- }
- }
- },
- (err) => {
- this.logger.fail(err);
- }
- );
- });
- }
- };
- var VerboseRenderer = _VerboseRenderer;
- VerboseRenderer.nonTTY = true;
- VerboseRenderer.rendererOptions = {
- useIcons: false,
- logEmptyTitle: true,
- logTitleChange: true
- };
-
- // src/utils/renderer.ts
- var renderers = {
- default: DefaultRenderer,
- simple: SimpleRenderer,
- verbose: VerboseRenderer,
- silent: SilentRenderer
- };
- function isRendererSupported(renderer) {
- return process.stdout.isTTY === true || renderer.nonTTY === true;
- }
- function getRendererClass(renderer) {
- if (typeof renderer === "string") {
- return renderers[renderer] || renderers.default;
- }
- return typeof renderer === "function" ? renderer : renderers.default;
- }
- function getRenderer(renderer, fallbackRenderer, fallbackCondition, silentCondition) {
- let returnValue;
- let ret = getRendererClass(renderer);
- returnValue = { renderer: ret, nonTTY: false };
- const evaluateSilent = assertFunctionOrSelf(silentCondition);
- const evaluateFallback = assertFunctionOrSelf(fallbackCondition);
- if (evaluateSilent) {
- ret = getRendererClass("silent");
- returnValue = { renderer: ret, nonTTY: true };
- } else if (!isRendererSupported(ret) || evaluateFallback) {
- ret = getRendererClass(fallbackRenderer);
- returnValue = { renderer: ret, nonTTY: true };
- }
- return returnValue;
- }
-
- // src/utils/uuid.ts
- function generateUUID() {
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
- const r = Math.random() * 16 || 0;
- const v = c === "x" ? r : r && 3 || 8;
- return v.toString(16);
- });
- }
-
- // src/lib/task.ts
- var Task = class extends Subject {
- constructor(listr, tasks, options, rendererOptions) {
- var _a2, _b, _c, _d;
- super();
- this.listr = listr;
- this.tasks = tasks;
- this.options = options;
- this.rendererOptions = rendererOptions;
- this.message = {};
- this.id = generateUUID();
- this.title = (_a2 = this.tasks) == null ? void 0 : _a2.title;
- this.initialTitle = (_b = this.tasks) == null ? void 0 : _b.title;
- this.task = this.tasks.task;
- this.skip = ((_c = this.tasks) == null ? void 0 : _c.skip) ?? false;
- this.enabledFn = ((_d = this.tasks) == null ? void 0 : _d.enabled) ?? true;
- this.rendererTaskOptions = this.tasks.options;
- this.renderHook$ = this.listr.renderHook$;
- this.subscribe(() => {
- this.renderHook$.next();
- });
- }
- set state$(state) {
- this.state = state;
- this.next({
- type: "STATE" /* STATE */,
- data: state
- });
- if (this.hasSubtasks() && this.hasFailed()) {
- for (const subtask of this.subtasks) {
- if (subtask.state === "PENDING" /* PENDING */) {
- subtask.state$ = "FAILED" /* FAILED */;
- }
- }
- }
- }
- set output$(data) {
- this.output = data;
- this.next({
- type: "DATA" /* DATA */,
- data
- });
- }
- set message$(data) {
- this.message = { ...this.message, ...data };
- this.next({
- type: "MESSAGE" /* MESSAGE */,
- data
- });
- }
- set title$(title) {
- this.title = title;
- this.next({
- type: "TITLE" /* TITLE */,
- data: title
- });
- }
- async check(ctx) {
- if (this.state === void 0) {
- this.enabled = await assertFunctionOrSelf(this.enabledFn, ctx);
- this.next({
- type: "ENABLED" /* ENABLED */,
- data: this.enabled
- });
- }
- }
- hasSubtasks() {
- var _a2;
- return ((_a2 = this.subtasks) == null ? void 0 : _a2.length) > 0;
- }
- isPending() {
- return this.state === "PENDING" /* PENDING */;
- }
- isSkipped() {
- return this.state === "SKIPPED" /* SKIPPED */;
- }
- isCompleted() {
- return this.state === "COMPLETED" /* COMPLETED */;
- }
- hasFailed() {
- return this.state === "FAILED" /* FAILED */;
- }
- isRollingBack() {
- return this.state === "ROLLING_BACK" /* ROLLING_BACK */;
- }
- hasRolledBack() {
- return this.state === "ROLLED_BACK" /* ROLLED_BACK */;
- }
- isRetrying() {
- return this.state === "RETRY" /* RETRY */;
- }
- isEnabled() {
- return this.enabled;
- }
- hasTitle() {
- return typeof (this == null ? void 0 : this.title) === "string";
- }
- isPrompt() {
- return !!this.prompt;
- }
- async run(context, wrapper) {
- var _a2, _b, _c, _d, _e;
- const handleResult = (result) => {
- if (result instanceof Listr) {
- result.options = { ...this.options, ...result.options };
- result.rendererClass = getRenderer("silent").renderer;
- result.renderHook$.subscribe(() => {
- this.renderHook$.next();
- });
- this.subtasks = result.tasks;
- result.err = this.listr.err;
- this.next({ type: "SUBTASK" /* SUBTASK */ });
- result = result.run(context);
- } else if (this.isPrompt()) {
- } else if (result instanceof Promise) {
- result = result.then(handleResult);
- } else if (result instanceof Readable) {
- result = new Promise((resolve, reject) => {
- result.on("data", (data) => {
- this.output$ = data.toString();
- });
- result.on("error", (error) => reject(error));
- result.on("end", () => resolve(null));
- });
- } else if (isObservable(result)) {
- result = new Promise((resolve, reject) => {
- result.subscribe({
- next: (data) => {
- this.output$ = data;
- },
- error: reject,
- complete: resolve
- });
- });
- }
- return result;
- };
- const startTime = Date.now();
- this.state$ = "PENDING" /* PENDING */;
- const skipped = await assertFunctionOrSelf(this.skip, context);
- if (skipped) {
- if (typeof skipped === "string") {
- this.message$ = { skip: skipped };
- } else if (this.hasTitle()) {
- this.message$ = { skip: this.title };
- } else {
- this.message$ = { skip: "Skipped task without a title." };
- }
- this.state$ = "SKIPPED" /* SKIPPED */;
- return;
- }
- try {
- const retryCount = ((_a2 = this.tasks) == null ? void 0 : _a2.retry) && ((_b = this.tasks) == null ? void 0 : _b.retry) > 0 ? this.tasks.retry + 1 : 1;
- for (let retries = 1; retries <= retryCount; retries++) {
- try {
- await handleResult(this.task(context, wrapper));
- break;
- } catch (err) {
- if (retries !== retryCount) {
- this.retry = { count: retries, withError: err };
- this.message$ = { retry: this.retry };
- this.title$ = this.initialTitle;
- this.output = void 0;
- wrapper.report(err, "WILL_RETRY" /* WILL_RETRY */);
- this.state$ = "RETRY" /* RETRY */;
- } else {
- throw err;
- }
- }
- }
- if (this.isPending() || this.isRetrying()) {
- this.message$ = { duration: Date.now() - startTime };
- this.state$ = "COMPLETED" /* COMPLETED */;
- }
- } catch (error) {
- if (this.prompt instanceof PromptError) {
- error = new Error(this.prompt.message);
- }
- if ((_c = this.tasks) == null ? void 0 : _c.rollback) {
- wrapper.report(error, "WILL_ROLLBACK" /* WILL_ROLLBACK */);
- try {
- this.state$ = "ROLLING_BACK" /* ROLLING_BACK */;
- await this.tasks.rollback(context, wrapper);
- this.state$ = "ROLLED_BACK" /* ROLLED_BACK */;
- this.message$ = { rollback: this.title };
- } catch (err) {
- this.state$ = "FAILED" /* FAILED */;
- wrapper.report(err, "HAS_FAILED_TO_ROLLBACK" /* HAS_FAILED_TO_ROLLBACK */);
- throw err;
- }
- if (((_d = this.listr.options) == null ? void 0 : _d.exitAfterRollback) !== false) {
- throw new Error(this.title);
- }
- } else {
- this.state$ = "FAILED" /* FAILED */;
- if (this.listr.options.exitOnError !== false && await assertFunctionOrSelf((_e = this.tasks) == null ? void 0 : _e.exitOnError, context) !== false) {
- wrapper.report(error, "HAS_FAILED" /* HAS_FAILED */);
- throw error;
- } else if (!this.hasSubtasks()) {
- wrapper.report(error, "HAS_FAILED_WITHOUT_ERROR" /* HAS_FAILED_WITHOUT_ERROR */);
- }
- }
- } finally {
- this.complete();
- }
- }
- };
-
- // src/lib/task-wrapper.ts
- import through from "through";
-
- // src/constants/clearline-regex.constants.ts
- var CLEAR_LINE_REGEX = "(?:\\u001b|\\u009b)\\[[\\=><~/#&.:=?%@~_-]*[0-9]*[\\a-ln-tqyz=><~/#&.:=?%@~_-]+";
- var BELL_REGEX = /\u0007/;
-
- // src/utils/prompt.ts
- function defaultCancelCallback(settings) {
- const errorMsg = "Cancelled prompt.";
- if (this instanceof TaskWrapper) {
- this.task.prompt = new PromptError(errorMsg);
- } else if ((settings == null ? void 0 : settings.error) !== false) {
- throw new Error(errorMsg);
- } else {
- return errorMsg;
- }
- }
- async function createPrompt(options, settings) {
- let cancelCallback;
- if (settings == null ? void 0 : settings.cancelCallback) {
- cancelCallback = settings.cancelCallback;
- } else {
- cancelCallback = defaultCancelCallback;
- }
- if (!Array.isArray(options)) {
- options = [{ ...options, name: "default" }];
- } else if (options.length === 1) {
- options = options.reduce((o, option) => {
- return [...o, Object.assign(option, { name: "default" })];
- }, []);
- }
- options = options.reduce((o, option) => {
- return [
- ...o,
- Object.assign(option, {
- stdout: this instanceof TaskWrapper ? (settings == null ? void 0 : settings.stdout) ?? this.stdout() : process.stdout,
- onCancel: cancelCallback.bind(this, settings)
- })
- ];
- }, []);
- let enquirer;
- if (settings == null ? void 0 : settings.enquirer) {
- enquirer = settings.enquirer;
- } else {
- try {
- const imported = await import("enquirer");
- enquirer = imported.default ? new imported.default() : new imported();
- } catch (e) {
- this.task.prompt = new PromptError("Enquirer is a peer dependency that must be installed separately.");
- throw new Error(e);
- }
- }
- if (this instanceof TaskWrapper) {
- enquirer.on("prompt", (prompt) => this.task.prompt = prompt);
- enquirer.on("submit", () => this.task.prompt = void 0);
- this.task.subscribe((event) => {
- if (event.type === "STATE" /* STATE */ && event.data === "SKIPPED" /* SKIPPED */) {
- if (this.task.prompt && !(this.task.prompt instanceof PromptError)) {
- this.task.prompt.submit();
- }
- }
- });
- }
- const response = await enquirer.prompt(options);
- if (options.length === 1) {
- return response.default;
- } else {
- return response;
- }
- }
- function destroyPrompt(throwError = false) {
- if (!this.task.prompt || this.task.prompt instanceof PromptError) {
- return;
- }
- if (throwError) {
- this.task.prompt.cancel();
- } else {
- this.task.prompt.submit();
- }
- }
-
- // src/lib/task-wrapper.ts
- var TaskWrapper = class {
- constructor(task, errors, options) {
- this.task = task;
- this.errors = errors;
- this.options = options;
- }
- get title() {
- return this.task.title;
- }
- set title(data) {
- this.task.title$ = data;
- }
- get output() {
- return this.task.output;
- }
- set output(data) {
- this.task.output$ = data;
- }
- newListr(task, options) {
- let tasks;
- if (typeof task === "function") {
- tasks = task(this);
- } else {
- tasks = task;
- }
- return new Listr(tasks, options, this.task);
- }
- report(error, type) {
- var _a2;
- if (this.task.options.collectErrors !== false) {
- this.errors.push(new ListrError(error, type, this.task));
- }
- this.task.message$ = { error: error.message ?? ((_a2 = this.task) == null ? void 0 : _a2.title) ?? "Task with no title." };
- }
- skip(message) {
- var _a2;
- this.task.state$ = "SKIPPED" /* SKIPPED */;
- if (message) {
- this.task.message$ = { skip: message ?? ((_a2 = this.task) == null ? void 0 : _a2.title) ?? "Task with no title." };
- }
- }
- isRetrying() {
- return this.task.isRetrying() ? this.task.retry : { count: 0 };
- }
- async prompt(options) {
- var _a2;
- return createPrompt.bind(this)(options, { ...(_a2 = this.options) == null ? void 0 : _a2.injectWrapper });
- }
- cancelPrompt(throwError = false) {
- return destroyPrompt.bind(this)(throwError);
- }
- stdout() {
- return through((chunk) => {
- chunk = chunk.toString();
- chunk = chunk.replace(new RegExp(CLEAR_LINE_REGEX, "gmi"), "");
- chunk = chunk.replace(new RegExp(BELL_REGEX, "gmi"), "");
- if (chunk !== "") {
- this.output = chunk;
- }
- });
- }
- run(ctx) {
- return this.task.run(ctx, this);
- }
- };
-
- // src/listr.ts
- var Listr = class {
- constructor(task, options, parentTask) {
- this.task = task;
- this.options = options;
- this.parentTask = parentTask;
- this.tasks = [];
- this.err = [];
- this.renderHook$ = new Subject2();
- this.path = [];
- var _a2, _b, _c;
- this.options = {
- ...{
- concurrent: false,
- renderer: "default",
- nonTTYRenderer: "verbose",
- exitOnError: true,
- exitAfterRollback: true,
- collectErrors: "minimal",
- registerSignalListeners: true
- },
- ...options
- };
- if (this.options.concurrent === true) {
- this.concurrency = Infinity;
- } else if (typeof this.options.concurrent === "number") {
- this.concurrency = this.options.concurrent;
- } else {
- this.concurrency = 1;
- }
- const renderer = getRenderer(this.options.renderer, this.options.nonTTYRenderer, (_a2 = this.options) == null ? void 0 : _a2.rendererFallback, (_b = this.options) == null ? void 0 : _b.rendererSilent);
- this.rendererClass = renderer.renderer;
- if (!renderer.nonTTY) {
- this.rendererClassOptions = this.options.rendererOptions;
- } else {
- this.rendererClassOptions = this.options.nonTTYRendererOptions;
- }
- this.add(task ?? []);
- if (parentTask) {
- this.path = [...parentTask.listr.path, parentTask.title];
- }
- if (this.options.registerSignalListeners) {
- process.once("SIGINT", () => {
- this.tasks.forEach(async (task2) => {
- if (task2.isPending()) {
- task2.state$ = "FAILED" /* FAILED */;
- }
- });
- this.renderer.end(new Error("Interrupted."));
- process.exit(127);
- }).setMaxListeners(0);
- }
- if ((_c = this.options) == null ? void 0 : _c.disableColor) {
- process.env.LISTR_DISABLE_COLOR = "1";
- }
- }
- add(task) {
- const tasks = Array.isArray(task) ? task : [task];
- tasks.forEach((task2) => {
- this.tasks.push(new Task(this, task2, this.options, { ...this.rendererClassOptions, ...task2.options }));
- });
- }
- async run(context) {
- var _a2;
- if (!this.renderer) {
- this.renderer = new this.rendererClass(this.tasks, this.rendererClassOptions, this.renderHook$);
- }
- this.renderer.render();
- this.ctx = ((_a2 = this.options) == null ? void 0 : _a2.ctx) ?? context ?? {};
- await this.checkAll(this.ctx);
- try {
- await pMap(
- this.tasks,
- async (task) => {
- await task.check(this.ctx);
- return this.runTask(task, this.ctx, this.err);
- },
- { concurrency: this.concurrency }
- );
- this.renderer.end();
- } catch (err) {
- if (this.options.exitOnError !== false) {
- this.renderer.end(err);
- throw err;
- }
- }
- return this.ctx;
- }
- checkAll(context) {
- return Promise.all(this.tasks.map((task) => task.check(context)));
- }
- runTask(task, context, errors) {
- if (!task.isEnabled()) {
- return Promise.resolve();
- }
- return new TaskWrapper(task, errors, this.options).run(context);
- }
- };
-
- // src/manager.ts
- var Manager = class {
- constructor(options) {
- this.options = options;
- this.err = [];
- this.tasks = [];
- }
- set ctx(ctx) {
- this.options.ctx = ctx;
- }
- add(tasks, options) {
- options = { ...this.options, ...options };
- this.tasks = [...this.tasks, this.indent(tasks, options)];
- }
- async runAll(options) {
- options = { ...this.options, ...options };
- const ctx = await this.run(this.tasks, options);
- this.tasks = [];
- return ctx;
- }
- newListr(tasks, options) {
- return new Listr(tasks, options);
- }
- indent(tasks, options, taskOptions) {
- options = { ...this.options, ...options };
- let newTask;
- if (typeof tasks === "function") {
- newTask = {
- ...taskOptions,
- task: (ctx) => this.newListr(tasks(ctx), options)
- };
- } else {
- newTask = {
- ...taskOptions,
- task: () => this.newListr(tasks, options)
- };
- }
- return newTask;
- }
- async run(tasks, options) {
- options = { ...this.options, ...options };
- const task = this.newListr(tasks, options);
- const ctx = await task.run();
- this.err = task.err;
- return ctx;
- }
- getRuntime(pipetime) {
- return `${Math.round(Date.now() - pipetime) / 1e3}s`;
- }
- };
- export {
- Listr,
- ListrError,
- ListrErrorTypes,
- ListrEventType,
- ListrTaskState,
- LogLevels,
- Logger,
- Manager,
- PromptError,
- createPrompt,
- destroyPrompt,
- figures
- };
|