import { t as TERMINAL_SIZE } from "./helpers-DBWrFADB.js";
import supportsColor from "supports-color";
import colors, { default as poppinssColors } from "@poppinss/colors";
import CliTable from "cli-table3";
import stringWidth from "string-width";
import logUpdate from "log-update";
import prettyHrtime from "pretty-hrtime";
import boxes from "cli-boxes";
//#region src/icons.ts
const { platform } = process;
/**
* A collection of platform specific icons
*/
const icons = platform === "win32" && !process.env.WT_SESSION ? {
	tick: "√",
	cross: "×",
	bullet: "*",
	nodejs: "♦",
	pointer: ">",
	info: "i",
	warning: "‼",
	squareSmallFilled: "[█]",
	borderVertical: "|"
} : {
	tick: "✔",
	cross: "✖",
	bullet: "●",
	nodejs: "⬢",
	pointer: "❯",
	info: "ℹ",
	warning: "⚠",
	squareSmallFilled: "◼",
	borderVertical: "│"
};
//#endregion
//#region src/colors.ts
/**
* Returns the colors instance based upon the environment.
*
* - The "raw" option returns the colors instance that prefix the color
*   transformations as raw text
* - The "silent" option returns the colors instance that performs no
*   color transformations
*/
function useColors(options = {}) {
	if (options.raw) return colors.raw();
	if (options.silent) return colors.silent();
	return colors.ansi();
}
//#endregion
//#region src/renderers/console.ts
/**
* Renders messages to the "stdout" and "stderr"
*/
var ConsoleRenderer = class {
	getLogs() {
		return [];
	}
	flushLogs() {}
	log(message) {
		console.log(message);
	}
	/**
	* Log message by overwriting the existing one
	*/
	logUpdate(message) {
		logUpdate(message);
	}
	/**
	* Persist the last logged message
	*/
	logUpdatePersist() {
		logUpdate.done();
	}
	/**
	* Log error
	*/
	logError(message) {
		console.error(message);
	}
};
//#endregion
//#region src/table.ts
/**
* Exposes the API to represent a table
*/
var Table = class {
	#state = {
		head: [],
		rows: []
	};
	/**
	* Size of the largest row for a given
	* column
	*/
	#columnSizes = [];
	/**
	* The renderer to use to output logs
	*/
	#renderer;
	/**
	* Logger configuration options
	*/
	#options;
	/**
	* The colors reference
	*/
	#colors;
	/**
	* Whether or not to render full width
	*/
	#renderFullWidth = false;
	/**
	* The column index that should take remaining
	* width.
	*/
	#fluidColumnIndex = 0;
	/**
	* Padding for columns
	*/
	#padding = 2;
	constructor(options = {}) {
		this.#options = {
			raw: options.raw === void 0 ? false : options.raw,
			chars: options.chars
		};
	}
	/**
	* Tracking the column size and keeping on the largest
	* one by tracking the content size
	*/
	#storeColumnSize(columns) {
		columns.forEach((column, index) => {
			const size = stringWidth(column);
			const existingSize = this.#columnSizes[index];
			if (!existingSize || existingSize < size) this.#columnSizes[index] = size;
		});
	}
	/**
	* Computes the col widths based when in fullwidth mode
	*/
	#computeColumnsWidth() {
		/**
		* Do not compute columns size, when rendering in full-width
		*/
		if (!this.#renderFullWidth) return;
		/**
		* The terminal columns
		*/
		let columns = TERMINAL_SIZE - (this.#columnSizes.length + 1);
		this.#state.colWidths = this.#state.colWidths || [];
		this.#columnSizes.forEach((column, index) => {
			/**
			* The column width will be the size of the biggest
			* text + padding left + padding right
			*/
			this.#state.colWidths[index] = this.#state.colWidths[index] || column + this.#padding * 2;
			/**
			* Compute remaining columns
			*/
			columns = columns - this.#state.colWidths[index];
		});
		/**
		* If there are remaining columns, then assign them
		* to the fluid column.
		*/
		if (columns) {
			const index = this.#fluidColumnIndex > this.#columnSizes.length - 1 ? 0 : this.#fluidColumnIndex;
			this.#state.colWidths[index] = this.#state.colWidths[index] + columns;
		}
	}
	/**
	* Returns the renderer for rendering the messages
	*/
	getRenderer() {
		if (!this.#renderer) this.#renderer = new ConsoleRenderer();
		return this.#renderer;
	}
	/**
	* Define a custom renderer. Logs to "stdout" and "stderr"
	* by default
	*/
	useRenderer(renderer) {
		this.#renderer = renderer;
		return this;
	}
	/**
	* Returns the colors implementation in use
	*/
	getColors() {
		if (!this.#colors) this.#colors = useColors();
		return this.#colors;
	}
	/**
	* Define a custom colors implementation
	*/
	useColors(color) {
		this.#colors = color;
		return this;
	}
	/**
	* Define table head
	*/
	head(headColumns) {
		this.#state.head = headColumns;
		this.#storeColumnSize(headColumns.map((column) => typeof column === "string" ? column : column.content));
		return this;
	}
	/**
	* Add a new table row
	*/
	row(row) {
		this.#state.rows.push(row);
		if (Array.isArray(row)) this.#storeColumnSize(row.map((cell) => typeof cell === "string" ? cell : cell.content));
		return this;
	}
	/**
	* Define custom column widths
	*/
	columnWidths(widths) {
		this.#state.colWidths = widths;
		return this;
	}
	/**
	* Toggle whether or render in full width or not
	*/
	fullWidth(renderFullWidth = true) {
		this.#renderFullWidth = renderFullWidth;
		return this;
	}
	/**
	* Define the column index that should take
	* will remaining width when rendering in
	* full-width
	*/
	fluidColumnIndex(index) {
		this.#fluidColumnIndex = index;
		return this;
	}
	/**
	* Render table
	*/
	render() {
		if (this.#options.raw) {
			this.getRenderer().log(this.#state.head.map((col) => typeof col === "string" ? col : col.content).join("|"));
			this.#state.rows.forEach((row) => {
				const content = Array.isArray(row) ? row.map((cell) => typeof cell === "string" ? cell : cell.content) : Object.keys(row);
				this.getRenderer().log(content.join("|"));
			});
			return;
		}
		this.#computeColumnsWidth();
		/**
		* Types of "cli-table3" are out of the sync from the
		* implementation
		*/
		const cliTable = new CliTable({
			head: this.#state.head,
			style: {
				"head": [],
				"border": ["dim"],
				"padding-left": 2,
				"padding-right": 2
			},
			wordWrap: true,
			...this.#state.colWidths ? { colWidths: this.#state.colWidths } : {},
			chars: this.#options.chars
		});
		this.#state.rows.forEach((row) => cliTable.push(row));
		this.getRenderer().log(cliTable.toString());
	}
};
//#endregion
//#region src/steps.ts
/**
* Steps class is used to display a series of sequential steps
* with counters, titles, content, and a visual left border
* connecting them.
*
* ```ts
* const steps = ui.steps()
*
* steps.add('Install dependencies', 'Run npm install to get started')
* steps.add('Configure app', 'Create a .env file with your settings')
* steps.add('Start server', 'Use npm start to launch the application')
*
* steps.render()
* ```
*/
var Steps = class {
	/**
	* Collection of steps to display
	*/
	#steps = [];
	/**
	* The renderer to use for rendering output
	*/
	#renderer;
	/**
	* Colors instance for styling output
	*/
	#colors;
	/**
	* Options for the steps
	*/
	#options;
	constructor(options = {}) {
		this.#options = { raw: options.raw === void 0 ? false : options.raw };
	}
	/**
	* Returns the renderer to use for output.
	* Defaults to ConsoleRenderer if not explicitly set
	*/
	getRenderer() {
		if (!this.#renderer) this.#renderer = new ConsoleRenderer();
		return this.#renderer;
	}
	/**
	* Define a custom renderer to use
	*/
	useRenderer(renderer) {
		this.#renderer = renderer;
		return this;
	}
	/**
	* Returns the colors instance
	*/
	getColors() {
		if (!this.#colors) this.#colors = useColors();
		return this.#colors;
	}
	/**
	* Define a custom colors instance
	*/
	useColors(colors) {
		this.#colors = colors;
		return this;
	}
	/**
	* Add a new step to the collection
	*
	* @param title - The step title/heading
	* @param content - Optional content/description for the step (supports ANSI formatting)
	*/
	add(title, content) {
		this.#steps.push({
			title,
			content
		});
		return this;
	}
	/**
	* Prepare the formatted output without rendering.
	* Useful for testing or custom output handling.
	*/
	prepare() {
		const colors = this.getColors();
		const lines = [];
		const stepCount = this.#steps.length;
		this.#steps.forEach((step, index) => {
			const stepNumber = index + 1;
			const isLast = stepNumber === stepCount;
			const counter = colors.cyan(`${stepNumber}.`);
			const title = colors.bold(step.title);
			lines.push(`${counter} ${title}`);
			if (step.content) step.content.split("\n").forEach((line) => {
				if (this.#options.raw) lines.push(line);
				else lines.push(`   ${line}`);
			});
			if (!isLast && !this.#options.raw) lines.push("");
		});
		return lines.join("\n");
	}
	/**
	* Render the steps to the configured renderer
	*/
	render() {
		const output = this.prepare();
		this.getRenderer().log(output);
	}
};
//#endregion
//#region src/logger/action.ts
/**
* Exposes the API to print actions in one of the following three states
*
* - failed
* - succeeded
* - skipped
*/
var Action = class {
	#startTime;
	/**
	* Action options
	*/
	#options;
	/**
	* Action message
	*/
	#message;
	/**
	* Reference to the colors implementation
	*/
	#colors;
	/**
	* The renderer to use for writing to the console
	*/
	#renderer;
	/**
	* Whether or not to display duration of the action
	*/
	#displayDuration = false;
	constructor(message, options = {}) {
		this.#message = message;
		this.#startTime = process.hrtime();
		this.#options = { dim: options.dim === void 0 ? false : options.dim };
	}
	/**
	* Format label
	*/
	#formatLabel(label, color) {
		label = this.getColors()[color](`${label.toUpperCase()}:`);
		if (this.#options.dim) return this.getColors().dim(label);
		return label;
	}
	/**
	* Format message
	*/
	#formatMessage(message) {
		if (this.#options.dim) return this.getColors().dim(message);
		return message;
	}
	/**
	* Format the suffix
	*/
	#formatSuffix(message) {
		message = `(${message})`;
		return this.getColors().dim(message);
	}
	/**
	* Format error
	*/
	#formatError(error) {
		return `\n    ${(typeof error === "string" ? error : error.stack || error.message).split("\n").map((line) => {
			if (this.#options.dim) line = this.getColors().dim(line);
			return `     ${this.getColors().red(line)}`;
		}).join("\n")}`;
	}
	/**
	* Returns the renderer for rendering the messages
	*/
	getRenderer() {
		if (!this.#renderer) this.#renderer = new ConsoleRenderer();
		return this.#renderer;
	}
	/**
	* Define a custom renderer.
	*/
	useRenderer(renderer) {
		this.#renderer = renderer;
		return this;
	}
	/**
	* Returns the colors implementation in use
	*/
	getColors() {
		if (!this.#colors) this.#colors = useColors();
		return this.#colors;
	}
	/**
	* Define a custom colors implementation
	*/
	useColors(color) {
		this.#colors = color;
		return this;
	}
	/**
	* Toggle whether to display duration for completed
	* tasks or not.
	*/
	displayDuration(displayDuration = true) {
		this.#displayDuration = displayDuration;
		return this;
	}
	/**
	* Prepares the message to mark action as successful
	*/
	prepareSucceeded() {
		let logMessage = `${this.#formatLabel("done", "green")}    ${this.#formatMessage(this.#message)}`;
		if (this.#displayDuration) logMessage = `${logMessage} ${this.#formatSuffix(prettyHrtime(process.hrtime(this.#startTime)))}`;
		return logMessage;
	}
	/**
	* Mark action as successful
	*/
	succeeded() {
		this.getRenderer().log(this.prepareSucceeded());
	}
	/**
	* Prepares the message to mark action as skipped
	*/
	prepareSkipped(skipReason) {
		let logMessage = `${this.#formatLabel("skipped", "cyan")} ${this.#formatMessage(this.#message)}`;
		if (skipReason) logMessage = `${logMessage} ${this.#formatSuffix(skipReason)}`;
		return logMessage;
	}
	/**
	* Mark action as skipped. An optional skip reason can be
	* supplied
	*/
	skipped(skipReason) {
		this.getRenderer().log(this.prepareSkipped(skipReason));
	}
	/**
	* Prepares the message to mark action as failed
	*/
	prepareFailed(error) {
		return `${this.#formatLabel("failed", "red")}  ${this.#formatMessage(this.#message)} ${this.#formatError(error)}`;
	}
	/**
	* Mark action as failed. An error message is required
	*/
	failed(error) {
		this.getRenderer().logError(this.prepareFailed(error));
	}
};
//#endregion
//#region src/logger/spinner.ts
/**
* Textual spinner to print a message with dotted progress
* bar.
*/
var Spinner = class {
	#animator = {
		frames: [
			".  ",
			".. ",
			"...",
			" ..",
			"  .",
			"   "
		],
		interval: 200,
		index: 0,
		getFrame() {
			return this.frames[this.index];
		},
		advance() {
			this.index = this.index + 1 === this.frames.length ? 0 : this.index + 1;
			return this.index;
		}
	};
	/**
	* The state of the spinner
	*/
	#state = "idle";
	/**
	* Spinner message
	*/
	#message;
	/**
	* The renderer to use for writing to the console
	*/
	#renderer;
	/**
	* Custom method to handle animation result
	*/
	#spinnerWriter;
	constructor(message) {
		this.#message = message;
	}
	/**
	* Loop over the message and animate the spinner
	*/
	#animate() {
		if (this.#state !== "running") return;
		/**
		* Do not write when in silent mode
		*/
		if (this.#message.silent) return;
		const frame = this.#animator.getFrame();
		if (this.#spinnerWriter) this.#spinnerWriter(`${this.#message.render()} ${frame}`);
		else this.getRenderer().logUpdate(`${this.#message.render()} ${frame}`);
		setTimeout(() => {
			this.#animator.advance();
			this.#animate();
		}, this.#animator.interval);
	}
	/**
	* Returns the renderer for rendering the messages
	*/
	getRenderer() {
		if (!this.#renderer) this.#renderer = new ConsoleRenderer();
		return this.#renderer;
	}
	/**
	* Define the custom renderer
	*/
	useRenderer(renderer) {
		this.#renderer = renderer;
		return this;
	}
	/**
	* Star the spinner
	*/
	start() {
		this.#state = "running";
		this.#animate();
		return this;
	}
	/**
	* Update spinner
	*/
	update(text, options) {
		if (this.#state !== "running") return this;
		Object.assign(this.#message, {
			text,
			...options
		});
		return this;
	}
	/**
	* Stop spinner
	*/
	stop() {
		this.#state = "stopped";
		this.#animator.index = 0;
		if (!this.#spinnerWriter && !this.#message.silent) {
			this.getRenderer().logUpdate(`${this.#message.render()} ${this.#animator.frames[2]}`);
			this.getRenderer().logUpdatePersist();
		}
	}
	/**
	* Tap into spinner to manually write the
	* output.
	*/
	tap(callback) {
		this.#spinnerWriter = callback;
		return this;
	}
};
//#endregion
//#region src/renderers/memory.ts
/**
* Keeps log messages within memory. Useful for testing
*/
var MemoryRenderer = class {
	#logs = [];
	getLogs() {
		return this.#logs;
	}
	flushLogs() {
		this.#logs = [];
	}
	/**
	* Log message
	*/
	log(message) {
		this.#logs.push({
			message,
			stream: "stdout"
		});
	}
	/**
	* For memory renderer the logUpdate is similar to log
	*/
	logUpdate(message) {
		this.log(message);
	}
	/**
	* Its a noop
	*/
	logUpdatePersist() {}
	/**
	* Log message as error
	*/
	logError(message) {
		this.#logs.push({
			message,
			stream: "stderr"
		});
	}
};
//#endregion
//#region src/logger/main.ts
/**
* CLI logger to log messages to the console. The output is consistently
* formatted.
*/
var Logger = class {
	/**
	* Logger configuration options
	*/
	#options;
	/**
	* Reference to the colors implementation
	*/
	#colors;
	/**
	* The renderer to use to output logs
	*/
	#renderer;
	getLogs() {
		return this.getRenderer().getLogs();
	}
	flushLogs() {
		this.getRenderer().flushLogs();
	}
	constructor(options = {}) {
		const dimOutput = options.dim === void 0 ? false : options.dim;
		this.#options = {
			dim: dimOutput,
			dimLabels: options.dimLabels === void 0 ? dimOutput : options.dimLabels
		};
	}
	/**
	* Color the logger label
	*/
	#colorizeLabel(color, text) {
		text = this.getColors()[color](text);
		if (this.#options.dimLabels) return `[ ${this.getColors().dim(text)} ]`;
		return `[ ${text} ]`;
	}
	/**
	* Returns the label for a given logging type
	*/
	#getLabel(type) {
		switch (type) {
			case "success": return this.#colorizeLabel("green", type);
			case "error":
			case "fatal": return this.#colorizeLabel("red", type);
			case "warning": return this.#colorizeLabel("yellow", "warn");
			case "info": return this.#colorizeLabel("blue", type);
			case "debug": return this.#colorizeLabel("cyan", type);
			case "await": return this.#colorizeLabel("cyan", "wait");
		}
	}
	/**
	* Appends the suffix to the message
	*/
	#addSuffix(message, suffix) {
		if (!suffix) return message;
		return `${message} ${this.getColors().dim().yellow(`(${suffix})`)}`;
	}
	/**
	* Appends duration to the message
	*/
	#addDuration(message, duration) {
		if (!duration) return message;
		return `${message} ${this.getColors().dim(`(${prettyHrtime(process.hrtime(duration))})`)}`;
	}
	/**
	* Prepends the prefix to the message. We do not DIM the prefix, since
	* gray doesn't have much brightness already
	*/
	#addPrefix(message, prefix) {
		if (!prefix) return message;
		prefix = prefix.replace(/%time%/, (/* @__PURE__ */ new Date()).toISOString());
		return `${this.getColors().dim(`[${prefix}]`)} ${message}`;
	}
	/**
	* Prepends the prefix to the message
	*/
	#prefixLabel(message, label) {
		return `${label} ${message}`;
	}
	/**
	* Decorate message string
	*/
	#decorateMessage(message) {
		if (this.#options.dim) return this.getColors().dim(message);
		return message;
	}
	/**
	* Decorate error stack
	*/
	#formatStack(stack) {
		if (!stack) return "";
		return `\n${stack.split("\n").splice(1).map((line) => {
			if (this.#options.dim) line = this.getColors().dim(line);
			return `      ${this.getColors().red(line)}`;
		}).join("\n")}`;
	}
	/**
	* Returns the renderer for rendering the messages
	*/
	getRenderer() {
		if (!this.#renderer) this.#renderer = new ConsoleRenderer();
		return this.#renderer;
	}
	/**
	* Define a custom renderer to output logos
	*/
	useRenderer(renderer) {
		this.#renderer = renderer;
		return this;
	}
	/**
	* Returns the colors implementation in use
	*/
	getColors() {
		if (!this.#colors) this.#colors = useColors();
		return this.#colors;
	}
	/**
	* Define a custom colors implementation
	*/
	useColors(color) {
		this.#colors = color;
		return this;
	}
	/**
	* Log message
	*/
	log(message) {
		this.getRenderer().log(message);
	}
	/**
	* Log message by updating the existing line
	*/
	logUpdate(message) {
		this.getRenderer().logUpdate(message);
	}
	/**
	* Persist log line written using the `logUpdate`
	* method.
	*/
	logUpdatePersist() {
		this.getRenderer().logUpdatePersist();
	}
	/**
	* Log error message using the renderer. It is similar to `console.error`
	* but uses the underlying renderer instead
	*/
	logError(message) {
		this.getRenderer().logError(message);
	}
	/**
	* Prepares the success message
	*/
	prepareSuccess(message, options) {
		message = this.#decorateMessage(message);
		message = this.#prefixLabel(message, this.#getLabel("success"));
		message = this.#addPrefix(message, options?.prefix);
		message = this.#addSuffix(message, options?.suffix);
		message = this.#addDuration(message, options?.startTime);
		return message;
	}
	/**
	* Log success message
	*/
	success(message, options) {
		this.log(this.prepareSuccess(message, options));
	}
	/**
	* Prepares the error message
	*/
	prepareError(message, options) {
		message = typeof message === "string" ? message : message.message;
		message = this.#decorateMessage(message);
		message = this.#prefixLabel(message, this.#getLabel("error"));
		message = this.#addPrefix(message, options?.prefix);
		message = this.#addSuffix(message, options?.suffix);
		message = this.#addDuration(message, options?.startTime);
		return message;
	}
	/**
	* Log error message
	*/
	error(message, options) {
		this.logError(this.prepareError(message, options));
	}
	/**
	* Prepares the fatal message
	*/
	prepareFatal(message, options) {
		const stack = this.#formatStack(typeof message === "string" ? void 0 : message.stack);
		message = typeof message === "string" ? message : message.message;
		message = this.#decorateMessage(message);
		message = this.#prefixLabel(message, this.#getLabel("error"));
		message = this.#addPrefix(message, options?.prefix);
		message = this.#addSuffix(message, options?.suffix);
		message = this.#addDuration(message, options?.startTime);
		return `${message}${stack}`;
	}
	/**
	* Log fatal message
	*/
	fatal(message, options) {
		this.logError(this.prepareFatal(message, options));
	}
	/**
	* Prepares the warning message
	*/
	prepareWarning(message, options) {
		message = this.#decorateMessage(message);
		message = this.#prefixLabel(message, this.#getLabel("warning"));
		message = this.#addPrefix(message, options?.prefix);
		message = this.#addSuffix(message, options?.suffix);
		message = this.#addDuration(message, options?.startTime);
		return message;
	}
	/**
	* Log warning message
	*/
	warning(message, options) {
		this.log(this.prepareWarning(message, options));
	}
	/**
	* Prepares the info message
	*/
	prepareInfo(message, options) {
		message = this.#decorateMessage(message);
		message = this.#prefixLabel(message, this.#getLabel("info"));
		message = this.#addPrefix(message, options?.prefix);
		message = this.#addSuffix(message, options?.suffix);
		message = this.#addDuration(message, options?.startTime);
		return message;
	}
	/**
	* Log info message
	*/
	info(message, options) {
		this.log(this.prepareInfo(message, options));
	}
	/**
	* Prepares the debug message
	*/
	prepareDebug(message, options) {
		message = this.#decorateMessage(message);
		message = this.#prefixLabel(message, this.#getLabel("debug"));
		message = this.#addPrefix(message, options?.prefix);
		message = this.#addSuffix(message, options?.suffix);
		message = this.#addDuration(message, options?.startTime);
		return message;
	}
	/**
	* Log debug message
	*/
	debug(message, options) {
		this.log(this.prepareDebug(message, options));
	}
	/**
	* Log a message with a spinner
	*/
	await(text, options) {
		return new Spinner({
			logger: this,
			text,
			...options,
			render() {
				let decorated = this.logger.#decorateMessage(this.text);
				decorated = this.logger.#prefixLabel(decorated, this.logger.#getLabel("await"));
				decorated = this.logger.#addPrefix(decorated, this.prefix);
				decorated = this.logger.#addSuffix(decorated, this.suffix);
				return decorated;
			}
		}).useRenderer(this.getRenderer());
	}
	/**
	* Initiates a new action
	*/
	action(title) {
		return new Action(title, { dim: this.#options.dim }).useColors(this.getColors()).useRenderer(this.getRenderer());
	}
	/**
	* Create a new child instance of self
	*/
	child(options) {
		return new this.constructor(options).useColors(this.getColors()).useRenderer(this.getRenderer());
	}
	/**
	* Create a dummy logger that silently discards all output.
	* Useful when output must be suppressed, for example
	* inside a tasks-manager callback where the task widget
	* owns the terminal.
	*/
	dummy() {
		return new this.constructor().useColors(this.getColors()).useRenderer(new MemoryRenderer());
	}
};
//#endregion
//#region src/instructions.ts
/**
* The box styling used by the instructions
*/
const BOX = boxes.round;
/**
* The API to render instructions wrapped inside a box
*/
var Instructions = class {
	#state = { content: [] };
	/**
	* Renderer to use for rendering instructions
	*/
	#renderer;
	/**
	* Length of the widest line inside instructions content
	*/
	#widestLineLength = 0;
	/**
	* Number of white spaces on the left of the box
	*/
	#leftPadding = 4;
	/**
	* Number of white spaces on the right of the box
	*/
	#rightPadding = 8;
	/**
	* Number of empty lines at the top
	*/
	#paddingTop = 1;
	/**
	* Number of empty lines at the bottom
	*/
	#paddingBottom = 1;
	/**
	* Reference to the colors
	*/
	#colors;
	/**
	* Options
	*/
	#options;
	/**
	* Draws the border
	*/
	#drawBorder = (border, colors) => {
		return colors.dim(border);
	};
	constructor(options = {}) {
		this.#options = {
			icons: options.icons === void 0 ? true : options.icons,
			raw: options.raw === void 0 ? false : options.raw
		};
	}
	/**
	* Returns the length of the horizontal line
	*/
	#getHorizontalLength() {
		return this.#widestLineLength + this.#leftPadding + this.#rightPadding;
	}
	/**
	* Repeats text for given number of times
	*/
	#repeat(text, times) {
		return new Array(times + 1).join(text);
	}
	/**
	* Wraps content inside the left and right vertical lines
	*/
	#wrapInVerticalLines(content, leftWhitespace, rightWhitespace) {
		return `${this.#drawBorder(BOX.left, this.getColors())}${leftWhitespace}${content}${rightWhitespace}${this.#drawBorder(BOX.right, this.getColors())}`;
	}
	/**
	* Returns the top line for the box
	*/
	#getTopLine() {
		const horizontalLength = this.#getHorizontalLength();
		const horizontalLine = this.#repeat(this.#drawBorder(BOX.top, this.getColors()), horizontalLength);
		return `${this.#drawBorder(BOX.topLeft, this.getColors())}${horizontalLine}${this.#drawBorder(BOX.topRight, this.getColors())}`;
	}
	/**
	* Returns the bottom line for the box
	*/
	#getBottomLine() {
		const horizontalLength = this.#getHorizontalLength();
		const horizontalLine = this.#repeat(this.#drawBorder(BOX.bottom, this.getColors()), horizontalLength);
		return `${this.#drawBorder(BOX.bottomLeft, this.getColors())}${horizontalLine}${this.#drawBorder(BOX.bottomRight, this.getColors())}`;
	}
	/**
	* Returns the heading border bottom
	*/
	#getHeadingBorderBottom() {
		const horizontalLength = this.#getHorizontalLength();
		const horizontalLine = this.#repeat(this.#drawBorder(boxes.single.top, this.getColors()), horizontalLength);
		return this.#wrapInVerticalLines(horizontalLine, "", "");
	}
	/**
	* Decorates the instruction line by wrapping it inside the box
	* lines
	*/
	#getContentLine(line) {
		const leftWhitespace = this.#repeat(" ", this.#leftPadding);
		const rightWhitespace = this.#repeat(" ", this.#widestLineLength - line.width + this.#rightPadding);
		return this.#wrapInVerticalLines(line.text, leftWhitespace, rightWhitespace);
	}
	/**
	* Returns the heading line by applying padding
	*/
	#getHeading() {
		if (!this.#state.heading) return;
		return this.#getContentLine(this.#state.heading);
	}
	/**
	* Returns the formatted body
	*/
	#getBody() {
		if (!this.#state.content || !this.#state.content.length) return;
		const top = new Array(this.#paddingTop).fill("").map(this.#getEmptyLineNode);
		const bottom = new Array(this.#paddingBottom).fill("").map(this.#getEmptyLineNode);
		return top.concat(this.#state.content).concat(bottom).map((line) => this.#getContentLine(line)).join("\n");
	}
	/**
	* Returns node for a empty line
	*/
	#getEmptyLineNode() {
		return {
			text: "",
			width: 0
		};
	}
	/**
	* Returns the renderer for rendering the messages
	*/
	getRenderer() {
		if (!this.#renderer) this.#renderer = new ConsoleRenderer();
		return this.#renderer;
	}
	/**
	* Define a custom renderer. Logs to "stdout" and "stderr"
	* by default
	*/
	useRenderer(renderer) {
		this.#renderer = renderer;
		return this;
	}
	/**
	* Returns the colors implementation in use
	*/
	getColors() {
		if (!this.#colors) this.#colors = useColors();
		return this.#colors;
	}
	/**
	* Define a custom colors implementation
	*/
	useColors(color) {
		this.#colors = color;
		return this;
	}
	/**
	* Draw the instructions box in fullscreen
	*/
	fullScreen() {
		this.#widestLineLength = TERMINAL_SIZE - (this.#leftPadding + this.#rightPadding) - 2;
		return this;
	}
	/**
	* Attach a callback to self draw the borders
	*/
	drawBorder(callback) {
		this.#drawBorder = callback;
		return this;
	}
	/**
	* Define heading for instructions
	*/
	heading(text) {
		const width = stringWidth(text);
		if (width > this.#widestLineLength) this.#widestLineLength = width;
		this.#state.heading = {
			text,
			width
		};
		return this;
	}
	/**
	* Add new instruction. Each instruction is rendered
	* in a new line inside a box
	*/
	add(text) {
		text = this.#options.icons ? `${this.getColors().dim(icons.pointer)} ${text}` : `${text}`;
		const width = stringWidth(text);
		if (width > this.#widestLineLength) this.#widestLineLength = width;
		this.#state.content.push({
			text,
			width
		});
		return this;
	}
	prepare() {
		/**
		* Render content as it is in raw mode
		*/
		if (this.#options.raw) {
			let output = [];
			if (this.#state.heading) output.push(this.#state.heading.text);
			output = output.concat(this.#state.content.map(({ text }) => text));
			return output.join("\n");
		}
		const top = this.#getTopLine();
		const heading = this.#getHeading();
		const headingBorderBottom = this.#getHeadingBorderBottom();
		const body = this.#getBody();
		const bottom = this.#getBottomLine();
		let output = `${top}\n`;
		/**
		* Draw heading if it exists
		*/
		if (heading) output = `${output}${heading}`;
		/**
		* Draw the border between the heading and the body if
		* both exists
		*/
		if (heading && body) output = `${output}\n${headingBorderBottom}\n`;
		/**
		* Draw body if it exists
		*/
		if (body) output = `${output}${body}`;
		return `${output}\n${bottom}`;
	}
	/**
	* Render instructions
	*/
	render() {
		this.getRenderer().log(this.prepare());
	}
};
//#endregion
//#region src/tasks/task.ts
/**
* Task exposes a very simple API to create tasks with states, along with a
* listener to listen for the task state updates.
*
* The task itself has does not render anything to the console. The task
* renderers does that.
*/
var Task = class {
	#startTime;
	/**
	* Last logged line for the task
	*/
	#lastLogLine;
	/**
	* Define one or more update listeners
	*/
	#updateListeners = [];
	/**
	* Duration of the task. Updated after the task is over
	*/
	#duration;
	/**
	* Message set after completing the task. Can be an error or the
	* a success message
	*/
	#completionMessage;
	/**
	* Task current state
	*/
	#state = "idle";
	constructor(title) {
		this.title = title;
	}
	#notifyListeners() {
		for (let listener of this.#updateListeners) listener(this);
	}
	/**
	* Access the task state
	*/
	getState() {
		return this.#state;
	}
	/**
	* Get the time spent in running the task
	*/
	getDuration() {
		return this.#duration || null;
	}
	/**
	* Get error occurred while running the task
	*/
	getError() {
		return this.#completionMessage || null;
	}
	/**
	* Get task completion success message
	*/
	getSuccessMessage() {
		return typeof this.#completionMessage === "string" ? this.#completionMessage : null;
	}
	/**
	* Last logged line for the task
	*/
	getLastLoggedLine() {
		return this.#lastLogLine || null;
	}
	/**
	* Bind a listener to listen to the state updates of the task
	*/
	onUpdate(listener) {
		this.#updateListeners.push(listener);
		return this;
	}
	/**
	* Start the task
	*/
	start() {
		this.#state = "running";
		this.#startTime = process.hrtime();
		this.#notifyListeners();
		return this;
	}
	/**
	* Update task with log messages. Based upon the renderer
	* in use, it may only display one line at a time.
	*/
	update(message) {
		this.#lastLogLine = message;
		this.#notifyListeners();
		return this;
	}
	/**
	* Mark task as completed
	*/
	markAsSucceeded(message) {
		this.#state = "succeeded";
		this.#duration = prettyHrtime(process.hrtime(this.#startTime));
		this.#completionMessage = message;
		this.#notifyListeners();
		return this;
	}
	/**
	* Mark task as failed
	*/
	markAsFailed(error) {
		this.#state = "failed";
		this.#duration = prettyHrtime(process.hrtime(this.#startTime));
		this.#completionMessage = error;
		this.#notifyListeners();
		return this;
	}
};
//#endregion
//#region src/tasks/renderers/verbose.ts
/**
* Verbose renderer shows a detailed output of the tasks and the
* messages logged by a given task
*/
var VerboseRenderer = class {
	/**
	* Reference to the colors implementation
	*/
	#colors;
	/**
	* The renderer to use to output logs
	*/
	#renderer;
	/**
	* List of registered tasks
	*/
	#registeredTasks = [];
	#notifiedTasks = /* @__PURE__ */ new Set();
	constructor() {}
	/**
	* Format error
	*/
	#formatError(error) {
		if (typeof error === "string") return `${this.#getAnsiIcon("│", "dim")}${this.getColors().red(error)}`;
		if (!error.stack) return `${this.#getAnsiIcon("│", "dim")}${this.getColors().red(error.message)}`;
		return `${error.stack.split("\n").map((line) => `${this.#getAnsiIcon("│", "dim")} ${this.getColors().red(line)}`).join("\n")}`;
	}
	/**
	* Returns the ansi icon back when icons are enabled
	* or an empty string
	*/
	#getAnsiIcon(icon, color) {
		return this.getColors()[color](`${icon} `);
	}
	/**
	* Renders message for a running task
	*/
	#renderRunningTask(task) {
		if (this.#notifiedTasks.has(task.title)) {
			const lastLoggedLine = task.getLastLoggedLine();
			if (lastLoggedLine) this.getRenderer().log(`${this.#getAnsiIcon("│", "dim")}${lastLoggedLine}`);
			return;
		}
		this.getRenderer().log(`${this.#getAnsiIcon("┌", "dim")}${task.title}`);
		this.#notifiedTasks.add(task.title);
	}
	/**
	* Renders message for a succeeded task
	*/
	#renderSucceededTask(task) {
		const successMessage = task.getSuccessMessage();
		const icon = this.#getAnsiIcon("└", "dim");
		const status = this.getColors().green(successMessage || "Completed");
		const duration = this.getColors().dim(`(${task.getDuration()})`);
		this.getRenderer().log(`${icon}${status} ${duration}`);
	}
	/**
	* Renders message for a failed task
	*/
	#renderFailedTask(task) {
		const error = task.getError();
		if (error) this.getRenderer().logError(this.#formatError(error));
		const icon = this.#getAnsiIcon("└", "dim");
		const status = this.getColors().red("Failed");
		const duration = this.getColors().dim(`(${task.getDuration()})`);
		this.getRenderer().logError(`${icon}${status} ${duration}`);
	}
	/**
	* Renders a given task
	*/
	#renderTask(task) {
		switch (task.getState()) {
			case "running": return this.#renderRunningTask(task);
			case "succeeded": return this.#renderSucceededTask(task);
			case "failed": return this.#renderFailedTask(task);
		}
	}
	/**
	* Renders all tasks
	*/
	#renderTasks() {
		this.#registeredTasks.forEach((task) => this.#renderTask(task));
	}
	/**
	* Returns the renderer for rendering the messages
	*/
	getRenderer() {
		if (!this.#renderer) this.#renderer = new ConsoleRenderer();
		return this.#renderer;
	}
	/**
	* Define a custom renderer. Logs to "stdout" and "stderr"
	* by default
	*/
	useRenderer(renderer) {
		this.#renderer = renderer;
		return this;
	}
	/**
	* Returns the colors implementation in use
	*/
	getColors() {
		if (!this.#colors) this.#colors = useColors();
		return this.#colors;
	}
	/**
	* Define a custom colors implementation
	*/
	useColors(color) {
		this.#colors = color;
		return this;
	}
	/**
	* Register tasks to render
	*/
	tasks(tasks) {
		this.#registeredTasks = tasks;
		return this;
	}
	/**
	* Render all tasks
	*/
	render() {
		this.#registeredTasks.forEach((task) => task.onUpdate(($task) => this.#renderTask($task)));
		this.#renderTasks();
	}
};
//#endregion
//#region src/tasks/renderers/minimal.ts
/**
* As the name suggests, render tasks in minimal UI for better viewing
* experience.
*/
var MinimalRenderer = class {
	/**
	* Renderer options
	*/
	#options;
	/**
	* Reference to the colors implementation
	*/
	#colors;
	/**
	* The renderer to use to output logs
	*/
	#renderer;
	/**
	* List of registered tasks
	*/
	#registeredTasks = [];
	constructor(options) {
		this.#options = { icons: options.icons === void 0 ? true : options.icons };
	}
	/**
	* Format error
	*/
	#formatError(error) {
		let message = typeof error === "string" ? error : error.message;
		message = this.getColors().red(message);
		return `\n  ${message.split("\n").map((line) => `${line}`).join("\n")}`;
	}
	/**
	* Returns the pointer icon, if icons are not disabled.
	*/
	#getPointerIcon(color) {
		const icon = this.#options.icons ? `${icons.pointer} ` : "";
		if (!icon) return icon;
		return this.getColors()[color](icon);
	}
	/**
	* Returns the display string for an idle task
	*/
	#renderIdleTask(task) {
		return `${this.#getPointerIcon("dim")}${this.getColors().dim(task.title)}`;
	}
	/**
	* Returns the display string for a running task
	*/
	#renderRunningTask(task) {
		const lastLogLine = task.getLastLoggedLine();
		return `${this.#options.icons ? `${icons.pointer} ${task.title}` : task.title}\n  ${lastLogLine || ""}`;
	}
	/**
	* Returns the display string for a failed task
	*/
	#renderFailedTask(task) {
		const pointer = this.#getPointerIcon("red");
		const duration = this.getColors().dim(`(${task.getDuration()})`);
		let message = `${pointer}${task.title} ${duration}`;
		const error = task.getError();
		if (!error) return `${message}\n`;
		message = `${message}${this.#formatError(error)}`;
		return message;
	}
	/**
	* Returns the display string for a succeeded task
	*/
	#renderSucceededTask(task) {
		const pointer = this.#getPointerIcon("green");
		const duration = this.getColors().dim(`(${task.getDuration()})`);
		let message = `${pointer}${task.title} ${duration}`;
		const successMessage = task.getSuccessMessage();
		if (!successMessage) return `${message}\n`;
		message = `${message}\n  ${this.getColors().green(successMessage)}`;
		return message;
	}
	/**
	* Renders a given task
	*/
	#renderTask(task) {
		switch (task.getState()) {
			case "idle": return this.#renderIdleTask(task);
			case "running": return this.#renderRunningTask(task);
			case "succeeded": return this.#renderSucceededTask(task);
			case "failed": return this.#renderFailedTask(task);
		}
	}
	/**
	* Renders all tasks
	*/
	#renderTasks() {
		const lastTaskState = this.#registeredTasks[this.#registeredTasks.length - 1].getState();
		this.getRenderer().logUpdate(this.#registeredTasks.map((task) => this.#renderTask(task)).join("\n"));
		if (lastTaskState === "succeeded" || lastTaskState === "failed") this.getRenderer().logUpdatePersist();
	}
	/**
	* Returns the renderer for rendering the messages
	*/
	getRenderer() {
		if (!this.#renderer) this.#renderer = new ConsoleRenderer();
		return this.#renderer;
	}
	/**
	* Define a custom renderer. Logs to "stdout" and "stderr"
	* by default
	*/
	useRenderer(renderer) {
		this.#renderer = renderer;
		return this;
	}
	/**
	* Returns the colors implementation in use
	*/
	getColors() {
		if (!this.#colors) this.#colors = useColors();
		return this.#colors;
	}
	/**
	* Define a custom colors implementation
	*/
	useColors(color) {
		this.#colors = color;
		return this;
	}
	/**
	* Register tasks to render
	*/
	tasks(tasks) {
		this.#registeredTasks = tasks;
		return this;
	}
	/**
	* Render all tasks
	*/
	render() {
		this.#registeredTasks.forEach((task) => {
			task.onUpdate(() => this.#renderTasks());
		});
		this.#renderTasks();
	}
};
//#endregion
//#region src/tasks/renderers/raw.ts
/**
* Raw renderer shows a detailed output of the tasks without using any
* ansi characters
*/
var RawRenderer = class {
	/**
	* Reference to the colors implementation
	*/
	#colors;
	/**
	* The renderer to use to output logs
	*/
	#renderer;
	/**
	* List of registered tasks
	*/
	#registeredTasks = [];
	#notifiedTasks = /* @__PURE__ */ new Set();
	constructor() {}
	/**
	* Format error
	*/
	#formatError(error) {
		if (typeof error === "string") return `${this.getColors().red(error)}`;
		if (!error.stack) return `${this.getColors().red(error.message)}`;
		return `${error.stack.split("\n").map((line) => ` ${this.getColors().red(line)}`).join("\n")}`;
	}
	/**
	* Renders message for a running task
	*/
	#renderRunningTask(task) {
		if (this.#notifiedTasks.has(task.title)) {
			const lastLoggedLine = task.getLastLoggedLine();
			if (lastLoggedLine) this.getRenderer().log(lastLoggedLine);
			return;
		}
		this.getRenderer().log(`${task.title}\n${new Array(task.title.length + 1).join("-")}`);
		this.#notifiedTasks.add(task.title);
	}
	/**
	* Renders message for a succeeded task
	*/
	#renderSucceededTask(task) {
		const successMessage = task.getSuccessMessage();
		const status = this.getColors().green(successMessage || "completed");
		const duration = this.getColors().dim(`(${task.getDuration()})`);
		this.getRenderer().log(`${status} ${duration}\n`);
	}
	/**
	* Renders message for a failed task
	*/
	#renderFailedTask(task) {
		const error = task.getError();
		if (error) this.getRenderer().logError(this.#formatError(error));
		const status = this.getColors().red("failed");
		const duration = this.getColors().dim(`(${task.getDuration()})`);
		this.getRenderer().logError(`${status} ${duration}\n`);
	}
	/**
	* Renders a given task
	*/
	#renderTask(task) {
		switch (task.getState()) {
			case "running": return this.#renderRunningTask(task);
			case "succeeded": return this.#renderSucceededTask(task);
			case "failed": return this.#renderFailedTask(task);
		}
	}
	/**
	* Renders all tasks
	*/
	#renderTasks() {
		this.#registeredTasks.forEach((task) => this.#renderTask(task));
	}
	/**
	* Returns the renderer for rendering the messages
	*/
	getRenderer() {
		if (!this.#renderer) this.#renderer = new ConsoleRenderer();
		return this.#renderer;
	}
	/**
	* Define a custom renderer. Logs to "stdout" and "stderr"
	* by default
	*/
	useRenderer(renderer) {
		this.#renderer = renderer;
		return this;
	}
	/**
	* Returns the colors implementation in use
	*/
	getColors() {
		if (!this.#colors) this.#colors = useColors();
		return this.#colors;
	}
	/**
	* Define a custom colors implementation
	*/
	useColors(color) {
		this.#colors = color;
		return this;
	}
	/**
	* Register tasks to render
	*/
	tasks(tasks) {
		this.#registeredTasks = tasks;
		return this;
	}
	/**
	* Render all tasks
	*/
	render() {
		this.#registeredTasks.forEach((task) => task.onUpdate(($task) => this.#renderTask($task)));
		this.#renderTasks();
	}
};
//#endregion
//#region src/tasks/manager.ts
function TRANSFORM_ERROR(error) {
	if (typeof error === "string") return {
		isError: true,
		message: error
	};
	return error;
}
/**
* Exposes the API to create a group of tasks and run them in sequence
*/
var TaskManager = class {
	/**
	* Last handled error
	*/
	error;
	/**
	* Options
	*/
	#options;
	/**
	* The renderer to use for rendering tasks. The verbose renderer is
	* used When "raw" is set to true.
	*/
	#tasksRenderer;
	/**
	* A set of created tasks
	*/
	#tasks = [];
	/**
	* State of the tasks manager
	*/
	#state = "idle";
	constructor(options = {}) {
		this.#options = {
			icons: options.icons === void 0 ? true : options.icons,
			raw: options.raw === void 0 ? false : options.raw,
			verbose: options.verbose === void 0 ? false : options.verbose
		};
		/**
		* Using verbose renderer when in raw mode
		*/
		if (this.#options.raw) this.#tasksRenderer = new RawRenderer();
		else if (this.#options.verbose) this.#tasksRenderer = new VerboseRenderer();
		else
 /**
		* Otheriwse using the minimal renderer
		*/
		this.#tasksRenderer = new MinimalRenderer({ icons: this.#options.icons });
	}
	/**
	* Run a given task. The underlying code assumes that tasks are
	* executed in sequence.
	*/
	async #runTask(index) {
		const task = this.#tasks[index];
		if (!task) return;
		/**
		* Start the underlying task
		*/
		task.task.start();
		/**
		* Update task progress
		*/
		const update = (logMessage) => {
			task.task.update(logMessage);
		};
		/**
		* Invoke callback
		*/
		try {
			const response = await task.callback({
				error: TRANSFORM_ERROR,
				update
			});
			if (typeof response === "string") {
				task.task.markAsSucceeded(response);
				await this.#runTask(index + 1);
			} else {
				this.#state = "failed";
				task.task.markAsFailed(response);
			}
		} catch (error) {
			this.#state = "failed";
			this.error = error;
			task.task.markAsFailed(error);
		}
	}
	/**
	* Access the task state
	*/
	getState() {
		return this.#state;
	}
	/**
	* Register a new task
	*/
	add(title, callback) {
		this.#tasks.push({
			task: new Task(title),
			callback
		});
		return this;
	}
	/**
	* Register a new task, when the "conditional = true"
	*/
	addIf(conditional, title, callback) {
		if (conditional) this.add(title, callback);
		return this;
	}
	/**
	* Register a new task, when the "conditional = false"
	*/
	addUnless(conditional, title, callback) {
		if (!conditional) this.add(title, callback);
		return this;
	}
	/**
	* Get access to registered tasks
	*/
	tasks() {
		return this.#tasks.map(({ task }) => task);
	}
	/**
	* Returns the renderer for rendering the messages
	*/
	getRenderer() {
		return this.#tasksRenderer.getRenderer();
	}
	/**
	* Define a custom renderer. Logs to "stdout" and "stderr"
	* by default
	*/
	useRenderer(renderer) {
		this.#tasksRenderer.useRenderer(renderer);
		return this;
	}
	/**
	* Define a custom colors implementation
	*/
	useColors(color) {
		this.#tasksRenderer.useColors(color);
		return this;
	}
	/**
	* Run tasks
	*/
	async run() {
		if (this.#state !== "idle") return;
		this.#state = "running";
		this.#tasksRenderer.tasks(this.tasks()).render();
		await this.#runTask(0);
		if (this.#state === "running") this.#state = "succeeded";
	}
};
//#endregion
//#region index.ts
/**
* Create a new CLI UI instance.
*
* - The "raw" mode is tailored for testing
* - The "silent" mode should be used when the terminal does not support colors. We
*   automatically perform the detection
*/
function cliui(options = {}) {
	let mode = options.mode;
	/**
	* Use silent mode when not explicit mode is defined
	*/
	if (!mode && !supportsColor.stdout) mode = "silent";
	/**
	* Renderer to use
	*/
	let renderer = mode === "raw" ? new MemoryRenderer() : new ConsoleRenderer();
	/**
	* Colors instance in use
	*/
	let colors = useColors({
		silent: mode === "silent",
		raw: mode === "raw"
	});
	/**
	* Logger
	*/
	const logger = new Logger();
	logger.useRenderer(renderer);
	logger.useColors(colors);
	/**
	* Render instructions inside a box
	*/
	const instructions = () => {
		const instructionsInstance = new Instructions({
			icons: true,
			raw: mode === "raw"
		});
		instructionsInstance.useRenderer(renderer);
		instructionsInstance.useColors(colors);
		return instructionsInstance;
	};
	/**
	* Similar to instructions. But without the `pointer` icon
	*/
	const sticker = () => {
		const instructionsInstance = new Instructions({
			icons: false,
			raw: mode === "raw"
		});
		instructionsInstance.useRenderer(renderer);
		instructionsInstance.useColors(colors);
		return instructionsInstance;
	};
	/**
	* Initiates a group of tasks
	*/
	const tasks = (tasksOptions) => {
		const manager = new TaskManager({
			raw: mode === "raw",
			...tasksOptions
		});
		manager.useRenderer(renderer);
		manager.useColors(colors);
		return manager;
	};
	/**
	* Instantiate a new table
	*/
	const table = (tableOptions) => {
		const tableInstance = new Table({
			raw: mode === "raw",
			...tableOptions
		});
		tableInstance.useRenderer(renderer);
		tableInstance.useColors(colors);
		return tableInstance;
	};
	/**
	* Instantiate a new steps display
	*/
	const steps = () => {
		const stepsInstance = new Steps({ raw: mode === "raw" });
		stepsInstance.useRenderer(renderer);
		stepsInstance.useColors(colors);
		return stepsInstance;
	};
	return {
		colors,
		logger,
		table,
		tasks,
		steps,
		icons,
		sticker,
		instructions,
		switchMode(modeToUse) {
			mode = modeToUse;
			/**
			* Use memory renderer in raw mode, otherwise switch to
			* console renderer
			*/
			if (mode === "raw") this.useRenderer(new MemoryRenderer());
			else this.useRenderer(new ConsoleRenderer());
			this.useColors(useColors({
				silent: mode === "silent",
				raw: mode === "raw"
			}));
		},
		useRenderer(rendererToUse) {
			renderer = rendererToUse;
			logger.useRenderer(renderer);
		},
		useColors(colorsToUse) {
			colors = colorsToUse;
			logger.useColors(colors);
			this.colors = colors;
		}
	};
}
//#endregion
export { ConsoleRenderer, Instructions, Logger, MemoryRenderer, Steps, Table, TaskManager, cliui, poppinssColors as colors, icons };
