Node CLI
👜

Node CLI

Arguments parsing

Native

The process.argv property returns an array containing the command-line arguments passed when the Node.js process was launched.
JavaScript
const process = require("node:process");
process.argv.forEach((val, index) => {
  console.log(`${index}:${val}`);
});

//node process-argv.js one two three
/* outputs:
	0:/opt/nodejs/16.14.2/bin/node
	1:/workspaces/MyBlog/a.js
	2:one
	3:two
	4:three
*/
It returns an array。The first element is process.execPath, and the second is the javascript script file path,and others are parameters。

Commander (convenient cli arguments handles)

  1. Method chaining
  1. process arguments
  1. autohelp
JavaScript
#!/usr/bin/env node
const program = require("commander");
program
  .name("better-clone") // CLI name
  .version("0.0.1") // version
  .option("-v,--verbose", "verposity that can be increased");

// add commands
program
  .command("clone <source> [destination]") // clone is the command,source is  a required argument,destination is optional
  .option("-d,--depths <level>", "git clone depths")
  .description("cloe a repository into a newly created directory")
  .action((source, destination, cmdObj) => {
    console.log(
      `start cloning from ${source} to ${destination} with depth ${cmdObj.depths}`
    );
  });

program.parse(process.argv); // need pass process.argv to get arguments

// node ./commander.js clone ./src ./to --depths=2
// start cloning from ./src to ./to with depth 2

yargs

Build interactive command line tools, by parsing arguments and generating an elegant user interface.
yargs
yargs • Updated Jul 6, 2024
 

Iterative commands

inquirer.js (Friendly inputting)

  • flexible CLI iteraction
input、number、confirm、list、rawlist、expand、checkbox、password、Editor......
  • compatible with Windows/ OSX /Linux
JavaScript
const inquirer = require('inquirer')
inquirer
  .prompt([
    /* Pass your questions in here */
    { type: 'input', name: 'username', message: "What's ur name?" },
    {
        type: 'checkbox',
        name: 'gender',
        message: "What's ur gender?",
        choices: [ 'male', 'female' ]
    },
    {
        type: 'number',
        name: 'age',
        message: 'How old are u?',
        validate: input => Number.isNaN(Number(input))
            ? 'Number Required!' : true
        },
    {
        type: 'password',
        name: 'secret',
        message: 'Tell me a secret.',
        mask: 'x'
    }
  ])
  .then(answers => {
    console.log(`Answers are:\n ${JSON.stringify(answers)}`)
  })
  .catch(error => {
    if (error.isTtyError) {
      // Prompt couldn't be rendered in the current environment
    } else {
      // Something else when wrong
    }
  })

// node inquirer.js

React for interactive command-line apps

ink
vadimdemedes • Updated Jul 7, 2024
 

chalk - friendly outputs

  • easy to use
why chalk can output color texts on command?
ANSI Escape Code
JavaScript
const chalk=require('chalk')
const log=console.log
const chalk=require('chalk')
const log=console.log

log(chalk.blue('\nhello')+'world'+chalk.red('!\n'))

log(chalk.blue.bgRed.bold('Hello world!\n'))

log(chalk.blue('Hello','word','Foo','bar','biz','baz\n'))

log(chalk.red('Hello',chalk.underline.bgBlue('word')+'!\n'))

Ink

It provides the same component-based UI building experience that React offers in the browser, but for command-line apps
JavaScript
import React, {useState, useEffect} from 'react';
import {render, Text} from 'ink';

const Counter = () => {
	const [counter, setCounter] = useState(0);

	useEffect(() => {
		const timer = setInterval(() => {
			setCounter(previousCounter => previousCounter + 1);
		}, 100);

		return () => {
			clearInterval(timer);
		};
	}, []);

	return <Text color="green">{counter} tests passed</Text>;
};

render(<Counter />);

Node template rendering

Invoke other programs (shell.js 、execa)

  • CLI reuse
    • don’t need to reinvent git/ npm /yarn etc.
  • async operations to use computational intense operations
  • Node use child_process module to create new process
    • cp.exec 、 cp.spawn

shell.js

JavaScript
const shell = require('shelljs');
if(!shell.which('git')){
  shell.echo('Sorry, this script requires git')
  shell.exit(1)
}
shell.rm('-rf','out/Release')

shell.ls('*.js').forEach(function(file)=>{
  shell.sed('-i','BUILD_VSRSION','v0.1.2',file)
})
shell.cd('..')

if(shell.exec('git commit -am "Auto-commit"').code !==0){
  shell.echo('Error: Git commit failes')
  shell.exit(1)
}
  • support bash commands cross different platforms
  • get results synchronously

execa

JavaScript
const execa =require('execa');
(async ()=>{
  const {stdout}=await execa()
  console.log(stdout)
})()
JavaScript
const execa =require('execa');
execa('echo',['unicorns']).stdout.pipe(process.stdout)
  • promisify
  • support Shebang cross different platforms
  • acquire process exit signal
  • support windows
 

Other packages

Run multiple npm-scripts in parallel or sequential

check config schema

Event emitter working in browser

Hotkey configuration

hotkeys-js
jaywcjlove • Updated Jul 5, 2024