UNPKG

easy-cli-framework

Version:

A framework for building CLI applications that are robust and easy to maintain. Supports theming, configuration files, interactive prompts, and more.

231 lines (215 loc) 6.74 kB
import { DisplayOptions, EasyCLITheme } from '..'; import { Options, SingleBar } from 'cli-progress'; /** * Options for the progress bar * @interface ThemedProgressBarOptions * @type {object} * * @property {DisplayOptions} [barDisplayOptions] The display options for the progress bar * @property {boolean} [showPercentage=true] Whether to show the percentage complete * @property {DisplayOptions} [percentageDisplayOptions] The display options for the percentage complete * @property {boolean} [showTimeElapsed=false] Whether to show the time elapsed * @property {DisplayOptions} [timeElapsedDisplayOptions] The display options for the time elapsed * @property {boolean} [showTimeLeft=true] Whether to show the time left * @property {DisplayOptions} [timeLeftDisplayOptions] The display options for the time left * @property {boolean} [showCompleted=true] Whether to show the completed count * @property {DisplayOptions} [completedDisplayOptions] The display options for the completed count */ export type ThemedProgressBarOptions = { barDisplayOptions?: DisplayOptions; showPercentage?: boolean; percentageDisplayOptions?: DisplayOptions; showTimeLeft?: boolean; timeLeftDisplayOptions?: DisplayOptions; showTimeElapsed?: boolean; timeElapsedDisplayOptions?: DisplayOptions; showCompleted?: boolean; completedDisplayOptions?: DisplayOptions; }; /** * Default options for the progress bar * @hidden */ export const DEFAULT_PROGRESS_BAR_OPTIONS: ThemedProgressBarOptions = { // Default options for the progress bar barDisplayOptions: {}, // Whether to show the percentage complete showPercentage: true, // Display options for the percentage complete percentageDisplayOptions: {}, // Whether to show the time elapsed showTimeElapsed: false, // Display options for the time elapsed timeElapsedDisplayOptions: {}, // Whether to show the time left showTimeLeft: true, // Display options for the time left timeLeftDisplayOptions: {}, // Whether to show the completed count showCompleted: true, // Display options for the completed count completedDisplayOptions: {}, }; /** * A themed progress bar, can be overridden to add additional functionality * @template T * @class ThemedProgressBar * @param {EasyCLITheme} theme The theme to use * @param {string} name The name of the progress bar * @param {DisplayOptions} displayOptions The display options for the progress bar * @param {ThemedProgressBarOptions} [progressBarOptions=DEFAULT_PROGRESS_BAR_OPTIONS] The options for the progress bar * * @example * ```typescript * const progressBar = new ThemedProgressBar(theme, 'progress', displayOptions, { * showPercentage: true, * percentageDisplayOptions: 'info', * showTimeElapsed: true, * timeElapsedDisplayOptions: 'info', * showTimeLeft: true, * timeLeftDisplayOptions: 'info', * showCompleted: true, * completedDisplayOptions: 'info', * }); * ``` * */ export class ThemedProgressBar< T extends ThemedProgressBarOptions = ThemedProgressBarOptions > { protected name: string; protected theme: EasyCLITheme; protected displayOptions: DisplayOptions; protected progressBar: SingleBar | null; protected progressBarOptions: T; /** * Creates an instance of ThemedProgressBar * * @param {EasyCLITheme} theme The theme to use * @param {string} name The name of the progress bar * @param {DisplayOptions} displayOptions The display options for the progress bar * @param {ThemedProgressBarOptions} [progressBarOptions=DEFAULT_PROGRESS_BAR_OPTIONS] The options for the progress bar * * @example * ```typescript * const progressBar = new ThemedProgressBar(theme, 'progress', displayOptions, { * showPercentage: true, * percentageDisplayOptions: 'info', * }); * ``` */ constructor( theme: EasyCLITheme, name: string, displayOptions: DisplayOptions, progressBarOptions: ThemedProgressBarOptions = DEFAULT_PROGRESS_BAR_OPTIONS ) { this.theme = theme; this.name = name; this.displayOptions = displayOptions; this.progressBarOptions = { ...DEFAULT_PROGRESS_BAR_OPTIONS, ...progressBarOptions, } as T; } /** * An internal method to get the options for the progress bar * * @returns {Options} The options for the progress bar */ protected getOptions(): Options { const { barDisplayOptions, showPercentage, percentageDisplayOptions, showTimeElapsed, timeElapsedDisplayOptions, showTimeLeft, timeLeftDisplayOptions, showCompleted, completedDisplayOptions, } = this.progressBarOptions; const format = `${this.name} ${this.theme.formattedString( '[{bar}]', barDisplayOptions ?? {} )}`; const additions = []; if (showPercentage) additions.push( this.theme.formattedString( '{percentage}%', percentageDisplayOptions ?? {} ) ); if (showTimeElapsed) additions.push( this.theme.formattedString( '{duration_formatted} elapsed', timeElapsedDisplayOptions ?? {} ) ); if (showTimeLeft) additions.push( this.theme.formattedString( 'ETA: {eta_formatted}', timeLeftDisplayOptions ?? {} ) ); if (showCompleted) additions.push( this.theme.formattedString( '{value}/{total}', completedDisplayOptions ?? {} ) ); return { format: this.theme.formattedString( `${format} ${additions.join(' | ')}`, this.displayOptions ), hideCursor: true, fps: 60, stopOnComplete: true, clearOnComplete: true, }; } /** * Starts the progress bar * * @param {number} initial The initial number of items processed * @param {number} total The total number of items to process * @param {Record<string, any>} payload The payload to pass to the progress bar * @param {Options} options A set of options for the progress bar * * @returns {SingleBar} The progress bar * * @example * ```typescript * progressBar.start(0, 100); * ``` * */ public start( initial: number, total: number, payload: Record<string, any> = {}, options: Options = {} ): SingleBar { if (this.progressBar) return this.progressBar; this.progressBar = new SingleBar(options); this.progressBar.start(total, initial, payload); return this.progressBar; } /** * Stops the progress bar * * @example * ```typescript * progressBar.stop(); * ``` */ public stop() { this.progressBar?.stop(); this.progressBar = null; } }