diff --git a/README.md b/README.md index 8ba94e8..18eec2d 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,55 @@ const logger = new clogUtils({ }); ``` +## Progress bar + +The Progress Bar is a tool that helps you monitor the progress of your projects. It's especially useful when you want to visualize the completion status of a task or process. + +```javascript +// ES/Typescript +import { ProgressBar, progressbarPresets } from 'clog-utils'; + +// CommonJS +const { ProgressBar, progressbarPresets } = require("clog-utils"); + +const bar = new ProgressBar({ + maxValue: 100, + minValue: 0, + barDesign: { // Bar design is Optional + progressBarChar: "█", + emptyProgressBarChar: " ", + progressBarCharSuffix: ">" + } + // Or you can use Progress bar Presets: + // barDesign: progressbarPresets.modern - (Others: modern2, legacy, legacy2, shades, emoji) +}); + +bar.start(); + +bar.update(50); +bar.update(70); +bar.update(100, "Its Finished!"); // this will write the text to the right of the Progress bar. + +bar.end(); + +``` + +The `bar.update()` method also has an auto-stop feature, so using `bar.stop()` to stop the Progress Bar is not always necessary. + +## Progress Bar Preset Designs + +You can choose from a variety of preset designs for your Progress Bar by specifying the `barDesign` property: + +- `progressbarPresets.modern` +- `progressbarPresets.modern2` +- `progressbarPresets.legacy` +- `progressbarPresets.legacy2` +- And more + +Select a design that best suits your project's style. + +Enjoy tracking your progress with the Progress Bar! + ## Usages 💡 ### Warn and Error Functions ⚠️❌ @@ -249,4 +298,4 @@ const logger = new clogUtils({ ## License 📄 -This library is licensed under the Apache 2.0 License. See the [LICENSE](LICENSE) file for details. +This library is licensed under the Apache 2.0 License. See the [LICENSE](LICENSE) file for details. \ No newline at end of file diff --git a/package.json b/package.json index eccf1be..83cf16e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "clog-utils", - "version": "1.2.0", + "version": "2.0.0", "description": "Enhance Node.js console logging with clog-utils. Customize log presets, style messages, and reduce clutter.", "main": "lib/main.js", "types": "lib/main.d.ts", diff --git a/src/interfaces/progressbarOptions.ts b/src/interfaces/progressbarOptions.ts new file mode 100644 index 0000000..f3e26f0 --- /dev/null +++ b/src/interfaces/progressbarOptions.ts @@ -0,0 +1,54 @@ +export interface progressBarOptions { + maxValue: number; + minValue: number; + barDesign?: progressBarDesign; +}; + +export interface progressBarDesign { + progressBarChar: string; + emptyProgressBarChar: string; + progressBarCharSuffix: string; +}; + +export const defaultOptions: progressBarOptions = { + maxValue: 100, + minValue: 0, + barDesign: { + progressBarChar: "█", + emptyProgressBarChar: " ", + progressBarCharSuffix: ">" + }, +}; + +export const progressbarPresets: { [key: string]: progressBarDesign } = { + modern: { + progressBarChar: "█", + emptyProgressBarChar: " ", + progressBarCharSuffix: ">", + }, + modern2: { + progressBarChar: "■", + emptyProgressBarChar: "□", + progressBarCharSuffix: ">>", + }, + legacy: { + progressBarChar: "=", + emptyProgressBarChar: " ", + progressBarCharSuffix: ">" + }, + legacy2: { + progressBarChar: "-", + emptyProgressBarChar: " ", + progressBarCharSuffix: ">" + }, + shades: { + progressBarChar: "▓", + emptyProgressBarChar: "░", + progressBarCharSuffix: ">>", + }, + emoji: { + progressBarChar: "⬛", + emptyProgressBarChar: "⬜", + progressBarCharSuffix: "=>", + } +}; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index f526491..eaf0d32 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,6 @@ +import { progressBarOptions, progressBarDesign } from './interfaces/progressbarOptions'; import { Options, defaultOptions } from './interfaces/clogUtilsOptions'; +import { ProgressBar, progressbarPresets } from './progressbar'; import { LogPreset } from './interfaces/LogPreset'; import { format } from "node:util"; @@ -263,4 +265,4 @@ class clogUtils { }; }; -export { LogPreset, clogUtils }; \ No newline at end of file +export { LogPreset, clogUtils, ProgressBar, progressBarDesign, progressBarOptions, progressbarPresets }; \ No newline at end of file diff --git a/src/progressbar.ts b/src/progressbar.ts new file mode 100644 index 0000000..c088cc3 --- /dev/null +++ b/src/progressbar.ts @@ -0,0 +1,80 @@ +import { defaultOptions, progressBarOptions, progressbarPresets } from "./interfaces/progressbarOptions"; + +class ProgressBar { + private progressBarChar: string; + private emptyProgressBarChar: string; + private completed: number; + private length: number; + private maxValue: number; + private minValue: number; + private progressBarCharSuffix: string; + private isCompleted: boolean = false; + private defaultSettings: progressBarOptions = { + maxValue: 100, + minValue: 0, + barDesign: progressbarPresets.modern + } + + constructor(opt: progressBarOptions = defaultOptions) { + this.maxValue = opt.maxValue ?? this.defaultSettings.maxValue; + this.minValue = opt.minValue ?? this.defaultSettings.minValue; + this.completed = opt.minValue; + + this.progressBarChar = opt.barDesign?.progressBarChar ?? this.defaultSettings.barDesign!.progressBarChar; + this.emptyProgressBarChar = opt.barDesign?.emptyProgressBarChar ?? this.defaultSettings.barDesign!.emptyProgressBarChar; + this.progressBarCharSuffix = opt.barDesign?.progressBarCharSuffix ?? this.defaultSettings.barDesign!.progressBarCharSuffix; + + this.length = this.calculateLength(); + this.validateMinMaxValues(); + }; + + private validateMinMaxValues(): void { + if (this.minValue < 0) this.minValue = 0; + if (this.minValue > this.maxValue) this.maxValue = this.minValue; + }; + + private calculateLength(): number { + return (this.maxValue - this.minValue) / 2; + }; + + private render(...messages: any[]): void { + if (this.isCompleted) return; + if (this.maxValue < this.completed) return; + + const progress = (this.completed - this.minValue) / (this.maxValue - this.minValue); + const progressBarLength = Math.floor(this.length * progress); + const progressBar = this.progressBarChar.repeat(progressBarLength); + const emptyProgressBar = this.emptyProgressBarChar.repeat(this.length - progressBarLength); + const percentage = (progress * 100).toFixed(2); + + process.stdout.clearLine(0); + process.stdout.cursorTo(0); + + if (progress === 1) process.stdout.write(`[${this.progressBarChar.repeat(this.length)}${this.progressBarCharSuffix}] ${percentage}% | ${messages}`); + else process.stdout.write(`[${progressBar}${this.progressBarCharSuffix}${emptyProgressBar}] ${percentage}% | ${messages}`); + }; + + update(amount: number = 1, ...messages: any): void { + if (this.isCompleted) return; + + this.completed += amount; + if (this.completed < this.minValue) this.completed = this.minValue; + if (this.completed > this.maxValue) this.isCompleted = true, this.completed = this.maxValue; + if(!messages) messages = ""; + + + return this.render(messages); + }; + + end(): void { + this.isCompleted = true; + this.render(); + }; + + start(): void { + this.completed = this.minValue; + this.render(); + }; +}; + +export { ProgressBar, progressbarPresets }; \ No newline at end of file diff --git a/tests/test.ts b/tests/test.ts index 78e5e87..90ea6c2 100644 --- a/tests/test.ts +++ b/tests/test.ts @@ -1,4 +1,28 @@ -import { clogUtils } from "../src/main"; +import { ProgressBar, clogUtils } from "../src/main"; + +const bar = new ProgressBar({ + maxValue: 100, + minValue: 0, + barDesign: { + progressBarChar: "█", + emptyProgressBarChar: " ", + progressBarCharSuffix: ">" + } +}) + +function delay(ms: number) { + return new Promise( resolve => setTimeout(resolve, ms) ); +} +(async() => { + bar.start() + bar.update(20, `Hi!`); + await delay(2000) + bar.update(20, `Today its ${new Date().getFullYear()}`) + await delay(2000) + bar.update(20, `Always be happy!`) + await delay(2000) + bar.update(40, `Happy codings!`) +})(); const logger = new clogUtils({ consoleSave: { enabled: true, fileName: `consolesave_${Date.now()}`, path: "./saves" }, @@ -8,4 +32,4 @@ const logger = new clogUtils({ } }); -setInterval(() => { console.log("this is a Test message!", { preset: { prefix: "TEST", disableAntiSpam: false } }) }, 100) +setInterval(() => { console.log("this is a Test message!", { preset: { prefix: "TEST", disableAntiSpam: false } }) }, 1000) \ No newline at end of file