Node: 开发命令行程序 (Create Your Own CLI)

CLI, as an abbreviation of Command-line Interface, can receive user's input and give an immediate response in terminal.

In Node.js, globally installed packages have this kind of command line interface, taking 'http-server' as a brief example here:

What if we wanna make one like that? Easy, create files below first:

After that, we will create a my-cli.js file in 'bin' folder:

#!/usr/bin/env node

console.log('hello my-cli');

Note that: The first line indicates it's an executable file in Node.js environment, and that's indispensable。

Also package.json config is a necessary step:

{
  "author": "Scott",
  "license": "MIT",
  "name": "my-cli",
  "version": "1.0.0",
  "description": "my-cli",
  "bin": {
    "my-cli": "bin/my-cli.js"
  },
  "preferGlobal": "true"
}

As above, we provide a 'bin' configuration which has global command 'my-cli' pointing to 'bin/my-cli.js', and the last property 'preferGlobal' states clearly it supports global installation.

Now we open a terminal and run the following command in 'my-cli' dev folder:

As picture shows, we can run 'my-cli' command globally after installing our package via 'npm install -g .', magic happens!

Now we already complete a simple CLI program, but is it short of something? Em..., maybe we can add interactions for command line, and also, make it support two usage: global execution and normal import.

After a slight improvement on file structure:

As we see, a 'lib' folder was created for some logic files, a demo code shows below:

let chalk = require('chalk');

let sayHello = name => {
  // special fonts by 'chalk' lib
  return chalk.bold('Hello, ') + chalk.bold.bgRed(name);
};

exports.sayHello = sayHello;

We defined a 'sayHello' function and return a greeting word by passing the name, we also use the 'chalk' lib for special fonts in terminal.

Now let's have a glance at 'bin/my-cli.js':

#!/usr/bin/env node

let readline = require('readline');
let lib = require('../lib/index.js');

// interaction
let interface = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// question and answer
interface.question('What is your name? ', answer => {
  let greeting = lib.sayHello(answer);

  console.log(greeting);

  interface.close();
});

'readline' module is an encapsulation on stdin and stdout, used to prompt and receive user's input.

And last, some modifications should be done in package.json:

{
  "author": "Scott",
  "license": "MIT",
  "name": "my-cli",
  "version": "1.0.0",
  "description": "my-cli",
  "bin": {
    "my-cli": "bin/my-cli.js"
  },
  "main": "lib/index.js",
  "preferGlobal": "true",
  "dependencies": {
    "chalk": "^1.1.3"
  }
}

In addition to add 'bin' config, we also have the 'main' property, it's for the import in other lib, we will introduce it later.

Now we run 'npm install -g .' again to install globally, and open a new terminal:

As the image shows, our program received command arguments and printed the right result.

We mentioned above, our program can be a common package imported in other libs, now we create a test folder to show the demo:

This directory is simple, only includes a test.js and node_modules folder, and in node_modules it consists of my-cli folder:

Now we just take a look at the test.js:

let cli = require('my-cli');

let greeting = cli.sayHello('Jack');

console.log(greeting);

And then we run this file in terminal, and result as below:

At last, we can publish this package to npm repository, for this step, you may refer to the official docs.

Reference:

https://bretkikehara.wordpress.com/2013/05/02/nodejs-creating-your-first-global-module

https://nodejs.org/api/readline.html

posted @ 2018-05-05 19:45  liuhe688  阅读(201)  评论(0编辑  收藏  举报