如何开发一个基于node.js的CLI工具

第一步:初始化一个基于node的项目

mkdir jeeta
cd jeeta
npm init -y

第二步:初始化完成项目后,找到package.json文件并编辑添加bin属性的配置

{
  "name": "@jeeta/cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "bin": {
    "jeeta": "./bin/index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "module",
  "dependencies": {
    "chalk": "^4.1.2",
    "commander": "^9.4.0",
    "inquirer": "^9.1.2",
    "log-symbols": "^5.1.0",
    "ora": "^6.1.2"
  },
  "devDependencies": {
    "@babel/core": "^7.19.1",
    "@babel/eslint-parser": "^7.19.1",
    "eslint": "^8.23.1",
    "eslint-plugin-vue": "^9.5.1"
  }
}

其中的"jeeta":"./bin/index.js"就是cli命令执行是的入口文件,其中命令为jeeta;

当前在该项目的根目录执行jeeta还是会提示找不到命令的错误提示,稍等后续步骤执行项目的命令后才可。

第三步:编辑./bin/index.js文件

#!/usr/bin/env node

console.log('hello cli')

该入口文件只做了打印日志的输出操作,用于验证jeeta的命令执行;jeeta cli的正确使用有两种方法:

1、将该项目打包并发布到npm仓库然后按照到本地,这种适用于cli开发完毕并可发布的场景;

2、使用npm link命令进行本地安装。

我们选择方法2进行

npm link
# 如果本地安装了yarn可以使用
yarn link
# 本地安装完成后执行以下命令
> jeeta
hello cli

以上完成了最基本的cli工具的实现过程。

对应实际的CLI工具开发场景可能需要提供-h或--help帮助、create等,下面就实现一个包含一个jeeta命令帮助信息和jeeta create命令的CLI工具。

在项目中我们添加以下依赖:

包名称说明
commander提供了用户命令行输入 和 参数解析强大功能
chalk修改控制台中字符串的样式
log-symbols各种日志级别的彩色符号
npm i chalk@4.1.2 commander log-symbols@5.1.0 -S

依赖安装指定了版本,因最新的版本有比较大的变化,直接使用可能出现错误情况。

第一步:完善./bin/index.js文件脚本

#!/usr/bin/env node

import {Command} from 'commander'
import {commands} from '../src/commands/index.js'
import { readFile } from 'fs/promises';

/**
 * 注册option
 * @param {Object} commander commander实例
 * @param {Object} option 每个命令配置对象
 * @returns commander
 */
 const registerOption = (commander, option) => {
  return option && option.length ? commander.option(...option) : commander
}
/**
 * 注册action
 * @param {Object} commander commander实例
 * @param {Object} commandEle 每个命令配置对象
 * @returns commander
 */
const registerAction = (commander, commandEle) => {
  const { command, description, alias, options, action } = commandEle
  commander
    .command(command) // 命令的名称
    .description(description) // 命令的描述
    .alias(alias)
  // 循环options
  options && options.reduce(registerOption, commander)
  commander.action((options)=>{console.log(options)})
  return commander
}

const cli = new Command();
const pkg = JSON.parse(await readFile(new URL('../package.json', import.meta.url)));
// 循环创建命令
cli.version(pkg.version)

commands.reduce((cli,commandEle)=>{
    const { command, description, alias, options, action } = commandEle
    if(command){
      const thisCommand = cli.command(command) .description(description) .alias(alias);
      options && options.reduce(registerOption, thisCommand)
      thisCommand.action(action)
    }else{
      options && options.reduce(registerOption, cli)
      cli.action(action)
    }
    
  return cli
},cli)

cli.parse(process.argv)

node程序中,通过process.argv可获取到命令的参数,以数组返回;然后通过commander的program进行解析。

第二步:在根目录新建commands文件夹并新建文件index.js

mkdir src
cd src
mkdir commands
cd commands

编辑commands下的index.js文件内容

import createCmd from './create.js'
import helpCmd from './help.js'

export const commands = [
  createCmd,
  helpCmd
]

分别新建create.js和help.js

// create.js

import {successLog} from '../utils/log.js'
// create command
const createCmd ={
  command: 'create <projectName>',
  description: 'create a new project',
  alias: 'c',
  options: [
    ['-r, --react', 'react template'],
    ['-v, --vue', 'vue template'],
    ['-v2, --vue2', 'vue2 template'],
    ['-v3, --vue3', 'vue3 template']
  ],
  action: createAction,
  examples: ['-r', '--react', '-v', '--vue', '-v2', '--vue2', '-v3', '--vue3'].map((v) => `create projectName ${v}`)
}

function createAction(projectName, options) {
  console.log(projectName, options)
};
export default createCmd

// help.js
import chalk from 'chalk'
import {
  commands
} from './index.js';
import {infoLog} from '../utils/log.js'

const helpCmd = {
  options: [
    ['-h, --help', 'JEETA Help'],
  ],
  action: helpAction,
  examples: ['-h', '--help', '-V', '--version'].map((v) => `${v}`)
}

// help 
function helpAction() {
  infoLog(chalk.green('如何使用JEETA-CLI:'))
  commands.forEach((command, index) => {
    // console.log(command)
    console.log('  ', chalk.keyword('orange')(index + 1), `${command.command||'jeeta帮助'}命令`)
    command.examples && command.examples.forEach((example) => {
      console.log(`     - jeeta ${example}`)
    })
  });
};

export default helpCmd


以上代码段为两个js文件内容,注意拆分。

第三步在根目录新建utils文件夹及log.js

mkdir utils
cd utils

完善logs.js文件内容

import logSymbols from 'log-symbols';

export function successLog(message){
  console.log(logSymbols.success, message);
}

export function errLog(message){
  console.log(logSymbols.error, '打印错误日志');
  console.log(logSymbols.error, message);
}

export function infoLog(message){
  console.log(logSymbols.info, message);
}

export function warningLog(message){
  console.log(logSymbols.warning, message);
}

完成以上代码,执行jeeta -h命令或jeeta create demo命令查看效果。

             查看帮助信息命令

           创建项目命令

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMK7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值