IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> node cli 命令行工具实现 -> 正文阅读

[JavaScript知识库]node cli 命令行工具实现

node cli 命令行工具

初始化项目

mkdir tl && cd tl
npm init

修改package.json文件,添加bin字段,表明tl 是可执行文件,执行的文件是index.js

{
  "name": "y",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "bin": {
    "tl": "./index.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "license": "ISC",
}

创建index.js

#!/usr/bin/env node

console.log("你好")

安装

node i -g

此时就可以在命令行中执行tl命令了

交互

安装commander、inquirer、chalk(可选)

commander: 是完整的 node.js 命令行解决方案,能够帮助我们快速的实现cli命令;
inquirer: 是交互式命令行用户接口的集合,能够帮助我们快速的实现类似vue creat项目时的各种选择功能;
chalk: 是命令行美化工具;5.x版本只支持ES Module;

因为使用了chalk并且它只支持ES Module,所以需要修改package.json文件,添加type字段;也可以安装chalk4.x版本;

{
  ...
  "type": "module",
  ...
}

创建命令

首行的#!/usr/bin/env node是不可省略的,它表明了这是个node的可执行文件

#!/usr/bin/env node

import { Command } from 'commander'
import { readFile } from 'fs/promises'
import fs from 'fs'
import path from 'path'

const program = new Command()

const packageJson = JSON.parse(
  await readFile(new URL('./package.json', import.meta.url))
)

program.version(packageJson.version, '-v, --version', 'cli的最新版本')

program
  .command('gitreset')
    .description('执行回退到上一个版本')
    .action(async () => {
      try {
        await exec('git add .') // 解决未add的情况下不能reset
        handleExeRes(await exec('git reset --hard HEAD'))
      } catch (err) {
        console.log(chalk.red(`err: ${err}`))
      }
    })

program.parse(process.argv)

此时执行

tl -h

就可以看到已经有git reset命令了

创建交互式命令

使用inquirer完成用户交互式命令,最后拿到用户选择的结果做对应的操作;
如提前创建各种项目模板,如果用户选择的是vue3+ts,那么git clone vue3+ts的项目

import inquirer from 'inquirer'

const prompList = [
  ...
]
export default function (program) {
  program
    .command('create [projectName]')
    .description('创建新项目')
    .action((projectName) => {
      if (!projectName) {
        prompList.unshift({
          type: 'input',
          message: '项目名称:',
          name: 'projectName',
          default: 'newProject',
        })
      }

      inquirer.prompt(prompList).then((answers) => {
        console.log({ projectName, ...answers }) // 返回的结果,做处理
      })
    })
}

优化

当command多了后全写在index.js中就很麻烦,于是将gitreset命令放到command目录中

如图:

import chalk from 'chalk'
import child_process from 'child_process'
import util from 'util'
import { handleExeRes } from '../utils.js'

const exec = util.promisify(child_process.exec)

export default function (program) {
  program
    .command('gitreset')
    .description('执行回退到上一个版本')
    .action(async () => {
      try {
        await exec('git add .') // 解决未add的情况下不能reset
        handleExeRes(await exec('git reset --hard HEAD'))
      } catch (err) {
        console.log(chalk.red(`err: ${err}`))
      }
    })
}

这样index.js中就很清爽了,只需要import,然后执行就好了;

但是每添加一个命令都要引入一次有点麻烦,再优化一下,让它能够自动的引入commond下的命令

#!/usr/bin/env node

import { Command } from 'commander'
import { readFile } from 'fs/promises'
import fs from 'fs'
import { dirname, resolve } from 'path'
import { fileURLToPath } from 'url'

const program = new Command()
const __dirname = dirname(fileURLToPath(import.meta.url))

const packageJson = JSON.parse(
  await readFile(new URL('./package.json', import.meta.url))
)

program.version(packageJson.version, '-v, --version', 'cli的最新版本')

try {
  // 自动导入添加command
  const commandFiles = await fs.promises.readdir(resolve(__dirname, 'command'))
  for (let i = 0; i < commandFiles.length; i++) {
    const fileName = commandFiles[i]
    let model = await import(`./command/${fileName}`)
    if (typeof model?.default === 'function') {
      model.default(program)
    }
  }

  // 自动导入添加options
  const optionFiles = await fs.promises.readdir(resolve(__dirname, 'options'))
  for (let i = 0; i < optionFiles.length; i++) {
    const fileName = optionFiles[i]
    let model = await import(`./options/${fileName}`)
    model.default(program)
  }
} catch (err) {
  console.log('import err: ?>>>> ', err)
}
program.parse(process.argv)


完整项目地址: https://github.com/bfclouds/tl

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-31 23:55:34  更:2022-03-31 23:58:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:25:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码