🛠 用 Node.js 和 commander 快速搭建一个 CLI 工具骨架(gix 实战)
在上一篇中,我们聊了聊为什么我要开发一个 Git CLI 工具 ------ gix,解决我日常开发中繁琐重复的 Git 操作。
这篇文章,我们正式开工,从 0 到 1 搭建一个 CLI 工具的基础骨架,包含命令解析、参数传递、交互式输入等核心功能。
🧰 技术选型
工具 | 用途 |
---|---|
Node.js | 编写 CLI 工具的基础平台 |
TypeScript | 类型安全、增强开发体验 |
commander | 命令行参数解析 |
prompts | 交互式输入(比 inquirer 更轻量) |
chalk | 控制终端输出样式 |
execa | 执行 Git 命令 |
📁 项目初始化
我们用 pnpm 创建项目:
csharp
pnpm init
安装依赖:
sql
pnpm add commander prompts chalk execa
pnpm add -D typescript tsx @types/node
创建 tsconfig.json:
json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "Node",
"esModuleInterop": true,
"resolveJsonModule": true,
"outDir": "dist",
"strict": true
},
"include": ["src"]
}
🧱 文件结构
bash
/packages/cli
├── src
│ ├── index.ts # 入口文件
│ ├── commands
│ │ ├── squash.ts # squash 命令逻辑
│ │ └── merge.ts # merge 命令逻辑
│ └── utils
│ └── git.ts # Git 命令封装
├── package.json
└── tsconfig.json
🚪 Step 1:配置命令行入口
在 src/index.ts 中配置 CLI 主入口:
javascript
#!/usr/bin/env node
import { Command } from 'commander'
import { runSquash } from './commands/squash'
import { runMerge } from './commands/merge'
const program = new Command()
program.name('gix').description('Git 扩展工具集').version('0.0.1')
program
.command('squash')
.description('合并最近的多次提交')
.option('-n, --count <number>', '合并次数', '2')
.option('--all', '合并所有提交')
.action(runSquash)
program
.command('merge')
.description('交互式合并两个 commit')
.option('-f, --from <hash>', '起始 commit')
.option('-t, --to <hash>', '结束 commit')
.option('-m, --message <msg>', '合并后的 commit 信息')
.action(runMerge)
program.parse()
在 package.json 中加入:
json
"bin": {
"gix": "dist/index.js"
}
然后加上执行权限:
bash
chmod +x dist/index.js
✨ Step 2:实现 squash 命令逻辑
src/commands/squash.ts
typescript
import prompts from 'prompts'
import { execGit } from '../utils/git'
import chalk from 'chalk'
export async function runSquash(opts: { count: string; all?: boolean }) {
const count = opts.all ? 'HEAD~$(git rev-list --count HEAD)' : `HEAD~${opts.count}`
const { message } = await prompts({
type: 'text',
name: 'message',
message: '请输入新的 commit 信息:'
})
if (!message) {
console.log(chalk.red('❌ commit 信息不能为空'))
return
}
await execGit(`reset --soft ${count}`)
await execGit(`commit -m "${message}" --no-verify`)
console.log(chalk.green('🎉 squash 成功完成!'))
}
🔧 Step 3:封装 Git 命令工具函数
src/utils/git.ts
javascript
import { execa } from 'execa'
export async function execGit(cmd: string) {
const [cmdName, ...args] = cmd.split(' ')
await execa(cmdName, args, { stdio: 'inherit' })
}
✅ 试运行
bash
pnpm build
pnpm link
gix squash -n 2
输出:
sql
? 请输入新的 commit 信息:feat: 优化用户界面逻辑
🎉 squash 成功完成!
💡 小结
至此,我们完成了:
-
初始化 CLI 工具项目结构
-
配置 commander 命令解析
-
支持交互式输入(prompts)
-
执行 Git 命令(execa)
gix 的核心命令正在一步步搭建中 🚀
🔮 下一篇预告
下一篇我会分享如何构建更复杂的交互命令(如 gix merge),支持选择 commit、填写信息、自动推送,并通过 prompts 提升使用体验。
欢迎点赞 + 收藏 + 评论支持我继续更系列文章!