第一步:初始化一个基于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命令查看效果。
查看帮助信息命令
创建项目命令