记录一次命令行工具编写

工作中遇到这么一个场景

管理后台需要进行精确权限控制,比如页面,接口等等,需要在权限管理页面一个个手动添加页面以及各个页面使用的接口,甚至还有各个页面的按钮权限。这就导致一些问题

  1. 当前次开发新增很多页面以及接口时,手动添加是一件很麻烦的事情,还比较考验眼力,一不小心就配错了
  2. 环境迁移,测试环境,预发布环境,还有正式环境数据库都是隔离的,这就导致切换环境时需要重新配置,工作量巨大,费事费力

思考方案

实现一个命令行工具

  1. 提供一个配置模板
  2. 添加op时,执行初始化命令create-op -i,拷贝这个配置模板,更改成自己本次需要创建的内容
  3. 执行create-op -c env 实现不同环境下的op创建

创建op就具体业务具体分析了,无非就是根据配置,组装接口需要数据,然后依次手动调用接口即可,这里不做更多展开

实现

创建项目

npm init 初始化项目,-y或--yes,指定项目走默认配置

创建可执行脚本

创建一个bin文件夹,用来存放可执行命令对应的文件

创建可执行命令文件

js 复制代码
#!/usr/bin/env node

#! /usr/bin/env node 首行shebang语句,指定使用node解释程序执行脚本。 在不同的操作系统中,node [命令行]的位置不同,因此使用 env node 找到路径并执行

注册命令行命令,这一步是很重要的

当我们创建好bin文件后,会发现我们此时是可以直接执行这个文件的

那我们每次需要执行这个脚本时都要找到这个脚本的位置,显然是不太方便的。那我们应该怎么做呢?创建软链 如下所示在package.json 中添加bin字段映射命令关键字与可执行文件

js 复制代码
{
  ...
  "bin": {
    "create-op": "./bin/index.js"
  },
  ...
}

然后使用npm link安装本地模块,你就可以在{prefix}文件夹下看到你的命令了,当然这是因为我们现在是在本地开发模式下使用的这个方法

真正的开发中我们都是通过 npm install -g 或者 npm install安装远程模块的。在通过npm install -g全局安装的时候,npm会symlink可执行文件到{prefix}文件夹(Windows系统),npm install本地安装时,npm会symlink可执行文件到./node_modules/.bin 文件夹

可以使用npm prefix -g查看你的prefix目录

到这一步你就可以在任意位置打开命令行窗口,然后使用自己的命令了

如果想要取消软链,使用npm unlink -g <指令>的方式,当然你也可以去prefix文件夹下手动删除文件

命令行参数处理

此时就需要处理用户输入了,用户输入的就是命令行参数

js 复制代码
console.log(process.argv);

process为node进程中的全局变量,process.argv为一数组,数组内存储着命令行的各个部分,argv[0]为node的安装路径,argv[1]为主模块文件路径,剩下为子命令或参数。

看一个简单的例子

js 复制代码
#!/usr/bin/env node

const pkg = require('../package.json');
const opt = process.argv[2];
switch (opt) {
    case '-v':
        console.log(pkg.version);
        break;
}

开发中简单使用process.argv搭配switch使用确实可以解决不少问题,但是如果工具功能越来越丰富可能就会面临参数过多,顺序不固定,甚至不知道取第几个参数的问题也会出现

此时需要引入一个专门处理命令行参数的包了,这里以commander库为例

具体使用可以参考官网,这里举个例子

js 复制代码
const pkg = require('../package.json')
const { program } = require('commander');

// const { creatOp, creatOpInit } = require('../tool/index')

program
  .version(pkg.version)
  .option('-i, --init', '初始化op文件')
  .option('-c, --create <env>', '根据环境和op配置文件创建op')
  .action(opts => {
    // 约定初始化文件
    if (opts.init) {
      console.log('处理初始化op文件')
      // creatOpInit()
    }
    if (opts.create) {
      console.log('处理根据环境和op配置文件创建op')
      // creatOp()
    }
  })

  
program.parse();
命令行终端交互

咱们这个命令行工具只需要指令,没有与用户交互相关

当然你也可以搞得高级一些,比如预定义一些环境让用户选择

js 复制代码
const inquirer = require('inquirer')

  const questions = [{
    type: 'list',
    message: '请选择环境:',
    name: 'env',
    choices: [
      "dev",
      "fat",
      "uat"
    ]
}]

inquirer
  .prompt(
    questions
  )
  .then(answers => {
    console.log(JSON.stringify(answers,null,'  '))
  })
  .catch(error => {
    if (error.isTtyError) {
        console.log('isTtyError: ',error)
    } else {
        console.log('Others err: ',error)
    }
  })

发布npm包

现在命令行工具写好了,需要给别的同事也使用怎么办呢

总不能直接把代码包发过去,然后让同事npm link吧。所以就需要把命令行工具发布到npm源上去,同事就能npm install了,而且以后代码更新同步问题也变得简单了

登录

npm login登录得时候可能会遇到这个问题

npm notice Beginning October 4, 2021, all connections to the npm registry - including for package installation - must use TLS 1.2 or higher. You are currently using plaintext http to connect. Please visit the GitHub blog for more information: github.blog/2021-08-23-...

检查自己的源,是否是https地址

npm源地址

因为我们要发布到官方源上面,所以要确保源地址为官方地址https://registry.npmjs.com

可以通过 npm config get registry 命令查看当前 registry 源。 如需修改 registry 可通过以下四种方式:

  • 在全局配置 .npmrc ,可通过命令 npm config set registry= https://registry.npmjs.org/
  • 在当前项目配置,在当前项目中添加配置文件 .npmrc
js 复制代码
registry = https://registry.npmjs.org/
  • 发布包时指定 --registry 选项,npm publish ---registry=https://registry.npmjs.org/
  • 在当前项目的 package.json 中通过 publishConfig 字段指定。
js 复制代码
 "publicConfig": {
    "registry": "https://registry.npmjs.org/"
  }

发布

npm publish --access public

通过命令行选项 --access public 声明为公有包

相关推荐
正小安26 分钟前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序
_.Switch2 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
一路向前的月光2 小时前
Vue2中的监听和计算属性的区别
前端·javascript·vue.js
长路 ㅤ   2 小时前
vite学习教程06、vite.config.js配置
前端·vite配置·端口设置·本地开发
长路 ㅤ   2 小时前
vue-live2d看板娘集成方案设计使用教程
前端·javascript·vue.js·live2d
Fan_web2 小时前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常2 小时前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇3 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
Jiaberrr3 小时前
Element UI教程:如何将Radio单选框的圆框改为方框
前端·javascript·vue.js·ui·elementui
Tiffany_Ho4 小时前
【TypeScript】知识点梳理(三)
前端·typescript