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


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

    1. mkdir jeeta
    2. cd jeeta
    3. npm init -y

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

    1. {
    2. "name": "@jeeta/cli",
    3. "version": "1.0.0",
    4. "description": "",
    5. "main": "index.js",
    6. "bin": {
    7. "jeeta": "./bin/index.js"
    8. },
    9. "keywords": [],
    10. "author": "",
    11. "license": "ISC",
    12. "type": "module",
    13. "dependencies": {
    14. "chalk": "^4.1.2",
    15. "commander": "^9.4.0",
    16. "inquirer": "^9.1.2",
    17. "log-symbols": "^5.1.0",
    18. "ora": "^6.1.2"
    19. },
    20. "devDependencies": {
    21. "@babel/core": "^7.19.1",
    22. "@babel/eslint-parser": "^7.19.1",
    23. "eslint": "^8.23.1",
    24. "eslint-plugin-vue": "^9.5.1"
    25. }
    26. }

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

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

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

    1. #!/usr/bin/env node
    2. console.log('hello cli')
    '
    运行

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

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

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

    我们选择方法2进行

    1. npm link
    2. # 如果本地安装了yarn可以使用
    3. yarn link
    4. # 本地安装完成后执行以下命令
    5. > jeeta
    6. 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文件脚本

    1. #!/usr/bin/env node
    2. import {Command} from 'commander'
    3. import {commands} from '../src/commands/index.js'
    4. import { readFile } from 'fs/promises';
    5. /**
    6. * 注册option
    7. * @param {Object} commander commander实例
    8. * @param {Object} option 每个命令配置对象
    9. * @returns commander
    10. */
    11. const registerOption = (commander, option) => {
    12. return option && option.length ? commander.option(...option) : commander
    13. }
    14. /**
    15. * 注册action
    16. * @param {Object} commander commander实例
    17. * @param {Object} commandEle 每个命令配置对象
    18. * @returns commander
    19. */
    20. const registerAction = (commander, commandEle) => {
    21. const { command, description, alias, options, action } = commandEle
    22. commander
    23. .command(command) // 命令的名称
    24. .description(description) // 命令的描述
    25. .alias(alias)
    26. // 循环options
    27. options && options.reduce(registerOption, commander)
    28. commander.action((options)=>{console.log(options)})
    29. return commander
    30. }
    31. const cli = new Command();
    32. const pkg = JSON.parse(await readFile(new URL('../package.json', import.meta.url)));
    33. // 循环创建命令
    34. cli.version(pkg.version)
    35. commands.reduce((cli,commandEle)=>{
    36. const { command, description, alias, options, action } = commandEle
    37. if(command){
    38. const thisCommand = cli.command(command) .description(description) .alias(alias);
    39. options && options.reduce(registerOption, thisCommand)
    40. thisCommand.action(action)
    41. }else{
    42. options && options.reduce(registerOption, cli)
    43. cli.action(action)
    44. }
    45. return cli
    46. },cli)
    47. cli.parse(process.argv)

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

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

    1. mkdir src
    2. cd src
    3. mkdir commands
    4. cd commands

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

    1. import createCmd from './create.js'
    2. import helpCmd from './help.js'
    3. export const commands = [
    4. createCmd,
    5. helpCmd
    6. ]

    分别新建create.js和help.js

    1. // create.js
    2. import {successLog} from '../utils/log.js'
    3. // create command
    4. const createCmd ={
    5. command: 'create ',
    6. description: 'create a new project',
    7. alias: 'c',
    8. options: [
    9. ['-r, --react', 'react template'],
    10. ['-v, --vue', 'vue template'],
    11. ['-v2, --vue2', 'vue2 template'],
    12. ['-v3, --vue3', 'vue3 template']
    13. ],
    14. action: createAction,
    15. examples: ['-r', '--react', '-v', '--vue', '-v2', '--vue2', '-v3', '--vue3'].map((v) => `create projectName ${v}`)
    16. }
    17. function createAction(projectName, options) {
    18. console.log(projectName, options)
    19. };
    20. export default createCmd
    21. // help.js
    22. import chalk from 'chalk'
    23. import {
    24. commands
    25. } from './index.js';
    26. import {infoLog} from '../utils/log.js'
    27. const helpCmd = {
    28. options: [
    29. ['-h, --help', 'JEETA Help'],
    30. ],
    31. action: helpAction,
    32. examples: ['-h', '--help', '-V', '--version'].map((v) => `${v}`)
    33. }
    34. // help
    35. function helpAction() {
    36. infoLog(chalk.green('如何使用JEETA-CLI:'))
    37. commands.forEach((command, index) => {
    38. // console.log(command)
    39. console.log(' ', chalk.keyword('orange')(index + 1), `${command.command||'jeeta帮助'}命令`)
    40. command.examples && command.examples.forEach((example) => {
    41. console.log(` - jeeta ${example}`)
    42. })
    43. });
    44. };
    45. export default helpCmd

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

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

    1. mkdir utils
    2. cd utils

    完善logs.js文件内容

    1. import logSymbols from 'log-symbols';
    2. export function successLog(message){
    3. console.log(logSymbols.success, message);
    4. }
    5. export function errLog(message){
    6. console.log(logSymbols.error, '打印错误日志');
    7. console.log(logSymbols.error, message);
    8. }
    9. export function infoLog(message){
    10. console.log(logSymbols.info, message);
    11. }
    12. export function warningLog(message){
    13. console.log(logSymbols.warning, message);
    14. }

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

                 查看帮助信息命令

               创建项目命令

     

  • 相关阅读:
    自定义Dynamics 365实施和发布业务解决方案 - 4. 自动化业务流程
    架构之路15. 创业 - 厌倦
    第10章:有向图和偏序
    【Pygame实战】飞机射击大作:宇宙激战一触即发...这款超经典的射击游戏也该拿出来重启了~
    如何理解某一个开发框架的意图,从而去写和落代码文件位置不会出错
    docker部署mysql nginx redis
    《计算机校招之路》1.0.0 震撼发布
    杂学第十五篇:运维人常用linux命令(文件操作、k8s操作、日志查找操作等),动态更新
    Git的安装,安装git 2.37.2.2
    手写一个民用Tomcat (05)
  • 原文地址:https://blog.csdn.net/yidragon88xx/article/details/127065954