jb-node-lib
v1.31.0
Published
Common NodeJS functions to build apps
Readme
jb-node-lib
This node.js library contains a set of common utility functions to build NodeJs apps.
Instalation
The library is published on NPM, so you can easily install it with → npm install jb-node-lib
The library is written as a CommonJS module, so it can be imported as a CommonJS or ECMAScript Module.
ECMAScript
import { init, exit, cmd, sleep, dirExist, formatTime, formatSize } from 'jb-node-lib';
import { move, print, line, repeat, color, setColor, resetColor, printBox } from 'jb-node-lib';
import { black, red, green, yellow, blue, magenta, cyan, white, gray } from 'jb-node-lib';
// Remember to add "type": "module", in package.json to use ES modules
init();
print(yellow('Hello World!'), 10, 2);
exit();CommonJS
const { init, exit, cmd, sleep, dirExist, formatTime, formatSize } = require('jb-node-lib');
const { move, print, line, repeat, color, setColor, resetColor, printBox } = require('jb-node-lib');
const { black, red, green, yellow, blue, magenta, cyan, white, gray } = require('jb-node-lib');
init();
print(yellow('Hello World!'), 10, 2);
exit();Initialization
You can simply init everything calling init();
Most of the character printing is done through the process.stdout.write() api.
The cursor is moved to any position on the terminal using readline.cursorTo(process.stdout, x, y).
For this reason the library imports and uses the native resources internally.
const { exec } = require('child_process');
const readline = require('readline');If you want to use the keyboard to handle key strike events (like arrows), the init() function will set the readline and process.stdin:
readline.emitKeypressEvents(process.stdin);
if (process.stdin.setRawMode != null) { process.stdin.setRawMode(true); }So you cand simply listen to the event:
init();
process.stdin.on('keypress', (str, key) => {
if (key.name === 'c' && key.ctrl) { exit(); } // Ctrl+C stop signal
if (key.name === 'up') { doSomething(); }
if (key.name === 'down') { doSomething(); }
if (key.name === 'return') { doSomething(); }
if (key.name === 'space') { doSomething(); }
if (key.name === 'escape') { doSomething(); }
});List of Functions
The library exports functions of different purposes, although it focuses on printing elements on a terminal.
init()→ It initializes the readline and process stdin for keyboard event handling.exit()→ Terminates the process (process.exit(0)) and moves the cursor to the last line.cmd()→ Use it to run a terminal command within the app.sleep()→ Async function to await N milliseconds.move()→ Move the cursor to a given position in the terminal.print()→ Prints a string to a given position in the terminal.line()→ Joins multiple strings into one, each on its specific position.repeat()→ It returns a string repeating the given char N times.color()→ It returns the same string but wrapped with the control chars to print it colored.setColor()→ It prints a color control char, so every print after is done in that color.resetColor()→ Resets the current color to the default (after a setColor).printBox()→ It prints a line box to the given position, with additional colomns inside.dirExist()→ Validates whether a directory exists (true) or not (false).pad()→ A shortcut for.padStart()left padding.formatTime()→ It returns a string with a formated time.formatSize()→ It returns a string with a formated file size (KB, MB, GB...)setKeyboard()→ It listens to the keyboard events, and returns a keyboard object to handle them.createMenu()→ It returns a menu object to handle selections.color functions` → Shortcuts for coloring text strings.
init()
function init(clear = true): void
// Example:
init();This function initializes the readline and process.stdin so you can use the keyboard to handle key strike events.
It also clears all the characters on the terminal by default. You can opt out passing the clear = false parameter.
exit()
function exit(clear = false): void
// Example:
exit();This function terminates the process with process.exit(0) and moves the cursor to the last line.
It doesn't clears all the characters on the terminal by default, but you can pass clear = true to do it.
cmd()
function cmd(command: string): Promise<stdout>
// Example:
await cmd(`rm -rf ${file.path}`);Use it to run a terminal command within the app.
It uses the exec api to run the command, so it returns a promise when that is completed/error.
sleep()
function sleep(ms: number): Promise<void>
// Example:
await sleep(3000);Async function to await N milliseconds.
move()
function move(x = 1, y = 1): void
// Example:
move(30, 5);Move the cursor to a given position in the terminal.
print()
function print(text: string, posX ?: number, posY ?: number, color ?: string): void
// Example:
print('Hello World!');
print('Hello World!', 10, 3, 'yellow');Prints the string text to a given position posX, posY in the terminal.
It does not break the line. The next print will continue from the current cursor position (if not provided).
You can also add the color of the text (See colors palette).
line()
function line([..., strN: string, posN: number]): void
// Example:
print('Name Age ID', 0, 0); // Name Age ID
print('----------------------------------', 0, 1); // ----------------------------------
print(line('Syrax', 0, '7000', 14, '99999', 24), 0, 2); // Syrax 7000 99999
print(line('Vaghar', 0, '500', 14, '88888', 24), 0, 3); // Vaghar 500 88888
print(line('Me', 0, '25', 14, '11111', 24), 0, 4); // Me 25 11111Joins multiple strings into one, each on its specific position. It adds spaces beteween each.
This is very convinient when printing one line with different values in different columns, like in tables where every value should start on the same position, reagadless of the length of the previous value.
args should be pairs of strings and numbers, like: line('hello', 3, 'bye', 15, 'end', 50); where every par defines a value and a column position.
repeat()
function repeat(num: number, char: string): string
// Example:
repeat(10, '-'); // Returns: ----------Returns a string with 'char' repeated 'num' times
color()
function color(text: string, color = 'green', effect = 'bright', bgColor = ''): string
// Example:
print(color('This text is green', 'green'), 1, 1);
print(color('This text is green bg blinking text', 'white', 'blink', 'green'), 1, 2);It returns the same string but wrapped with the control chars to print it colored.
- 2nd argument (
color) → Text color - 3rd argument (
effect) → Text effect - 4th argument (
bgColor) → Background color
Colors: black, red, green, yellow, blue, magenta, cyan, white, gray
Effects: bright, dim, underscore, blink, reverse, hidden
There is a set of shortcut functions for every color.
See colors palette for more.
setColor()
function setColor(color = 'green', effect = 'bright', bgColor = ''): string
// Example:
setColor('green'); // Returns `\x1b[32m`
print('This text is green');
resetColor(); // Returns `\x1b[0m`
print('This text is white default');It prints a color control char, so every print after is done in that color. See colors palette for more.
resetColor()
function resetColor(): void
// Example:
setColor('green'); // Returns `\x1b[32m`
print('This text is green');
resetColor(); // Returns `\x1b[0m`
print('This text is white default');Resets the current color to the default (after a setColor()).
See colors palette for more.
printBox()
function printBox(posX = 0, posY = 0, width = 80, height = 20, cols = []): void;
// Example:
printBox(1, 1, 30, 7, [7, 15]);
// ┌──────┬───────┬───────────────┐
// │ │ │ │
// │ │ │ │
// └──────┴───────┴───────────────┘
// 1 7 15 31It prints a line box to the given position, with additional colomns inside.
dirExist()
function dirExist(fullPath: string): boolean;
// Example:
dirExist(`/home/barba/testDir`);Validates whether a directory exists (true) or not (false).
It uses try/catch, so it can be expensive in terms of performance (use it accordingly).
pad()
function pad(text: string, size = 1, char = '0'): string;
// Example:
pad(25, 4, '0'); // = 0025A shortcut for left padding .padStart().
formatTime()
function formatTime(ms: number): string;
// Example:
print(`Time (mm:ss) = ` + formatTime(160*1000)); // Time = 02:40It returns a string with a formated time (minutes and seconds). It doesn't account hours.
formatSize()
function formatSize(bytes = 0): string;
// Example:
print(`Size = ` + formatSize(160220)); // Size = 156.4 KB
print(`1 Byte = ` + formatSize(1)); // Size = 1 BIt returns a string with a formated file size (KB, MB, GB...)
setKeyboard()
function setKeyboard(keyPress = (str, key) => {}): keyboard{};
// Example:
const keyboard = setKeyboard();
keyboard.pushKeyMap({
keyEsc: () => { exit(); },
keyUp : () => { /* do something */ },
keyDown : () => { /* do something */ },
keyEnter: () => { /* do something */ },
});It listens to the keyboard events on process.stdin.on('keypress', (str, key) => {}), and returns a keyboard object to handle them.
You basically add a keyMaps, where you define an action for every key code.
You can add more than 1 keyMap (pushKeyMap/pop), so you can easily handle different actions on different situations, like moving from one menu to another.
The available methods are:
clear()→ Removes all current keyMaps.pushKeyMap(map)→ Adds a new keyMap, so that takes effect immediately.pop()→ Removes the current keyMap. If there were others before, those take effect in reverse order.disable()→ Disables any key action.enable()→ Enables them again.onKeyPress(callbackFn)→ To add extra logic on keypress.
In case you need to do something different on key press, you can add a callback function with onKeyPress().
Keymap actions will still run, right before the keyPress function.
Example:
const keyboard = setKeyboard((str, key) => print(`You pressed: ${key.name}`, 60, 0));
keyboard.pushKeyMap({
keyUp : () => { /* do something */ },
keyDown : () => { /* do something */ },
keyEnter: () => { /* do something */ },
});createMenu()
function createMenu([...op], posX = 0, posY = 0): menu{};
// Example:
const menu = createMenu([
{ code: 'op1', title: `Option 1` },
{ code: 'op2', title: `Option 2` },
{ code: 'op3', title: `Option 3` },
], 4, 2);
const keyboard = setKeyboard();
keyboard.pushKeyMap({
keyEsc: () => { exit(); },
keyUp : () => { menu.prev(); },
keyDown : () => { menu.next(); },
keyEnter: () => { selectMenuOption(menu.currOp()); },
});It returns a menu object to handle selections.
It keeps track of the options and current selection, pointint to it with an arrow.

You can use the following methods on the menu object:
print()→ To print all the options, highlighting the current selectionnext()→ Move the current selection to the next index.prev()→ Move the current selection to the previous index.move(sel)→ Move the current selection to the given index.currOp()→ Returns the object of the current selection (ops[sel]).
Color Functions
There is a set of color shortcut functions for every of the 9 colors, so you can improve verbosity:
black('Hello'); // = print(color('Hello', 'black'));
red('Hello'); // = print(color('Hello', 'red'));
green('Hello'); // = print(color('Hello', 'green'));
yellow('Hello'); // = print(color('Hello', 'yellow'));
blue('Hello'); // = print(color('Hello', 'blue'));
magenta('Hello'); // = print(color('Hello', 'magenta'));
cyan('Hello'); // = print(color('Hello', 'cyan'));
white('Hello'); // = print(color('Hello', 'white'));
gray('Hello'); // = print(color('Hello', 'gray'));Color Palette
There is a palette of 9 different colors you can use to print text:
print(color('This text is black', 'black'), 1, 1);
print(color('This text is red', 'red'), 1, 2);
print(color('This text is green', 'green'), 1, 3);
print(color('This text is yellow', 'yellow'), 1, 4);
print(color('This text is blue', 'blue'), 1, 5);
print(color('This text is magenta', 'magenta'), 1, 6);
print(color('This text is cyan', 'cyan'), 1, 7);
print(color('This text is white', 'white'), 1, 8);
print(color('This text is gray', 'gray'), 1, 9);
You can also use background colors, and 6 different effects:
- bright (default, means bold, not lighter)
- dim
- underscore
- blink
- reverse
- hidden
Further help
You can leave some comments on the project or contact me directly for more information.
