使用typescript快速开发一个cli的实现示例


Posted in Javascript onDecember 09, 2020

cli 的全称 command-line interface(命令行界面),也就是前端同学常用的脚手架,比如 yo、vue cli、react cli 等。

cli 可以方便我们快速创建项目,下图是引用 vue cli 的介绍:

使用typescript快速开发一个cli的实现示例

创建项目

运行下面的命令,创建一个项目:

npm init

执行命令完成后,可以看到项目根目录只有一个 package.json 文件。

使用typescript快速开发一个cli的实现示例

在 package.json 文件增加 bin 对象,并指定入口文件 dist/index.js。

在命令行运行需要在入口文件的第一行增加 #!/usr/bin/env node,告诉系统用 node 运行这个文件。

{
 "name": "cli-demo",
 "version": "0.0.1",
 "description": "cli demo",
 "keywords": [
 "cli"
 ],
 "bin": {
 "cli-demo": "dist/index.js"
 }
 ...
}

安装依赖

命令行工具,也会涉及到用户交互的动作,那么 node.js 是怎么实现呢?早有大佬提供了非常好的库,我们只要拿过来用,主要有两个库:

  • commander:完整的 node.js 命令行解决方案。
  • inquirer:交互式命令行工具。

将这两个库安装到项目里:

yarn add commander inquirer

由于是用 typescript 开发,再通过 rollup 打包,先安装相关的依赖库:

yarn add typescript rollup rollup-plugin-terser rollup-plugin-typescript2 @types/inquirer -D

配置

由于是用 typescript 开发,首先需要配置一下 tsconfig.json。

{
 "compilerOptions": {
 "target": "ES6",
 "module": "ESNext",
 "sourceMap": false,
 "declaration": false,
 "outDir": "./dist",
 "moduleResolution": "Node",
 "esModuleInterop": true,
 "resolveJsonModule": true,
 "removeComments": false,
 "importHelpers": true,
 "strict": true,
 "lib": ["ES6", "DOM"]
 },
 "include": ["src"]
}

接下来在根目录增加一个 rollup.config.js,把 typescript 代码编译成 javascript 代码。前面提到的要在第一行增加 #!/usr/bin/env node 来告诉系统用 node 运行,那么可以在 rollup.config.js 的 banner 选项,把 #!/usr/bin/env node 写在最前面。

import typescript from 'typescript'
import json from '@rollup/plugin-json'
import { terser } from 'rollup-plugin-terser'
import typescript2 from 'rollup-plugin-typescript2'

import { dependencies } from './package.json'

const external = Object.keys(dependencies || '')
const globals = external.reduce((prev, current) => {
 const newPrev = prev

 newPrev[current] = current
 return newPrev
}, {})

const defaultConfig = {
 input: './src/index.ts',
 output: {
 file: './dist/index.js',
 format: 'cjs',
 banner: '#!/usr/bin/env node',
 globals
 },
 external,
 plugins: [
 typescript2({
  exclude: 'node_modules/**',
  useTsconfigDeclarationDir: true,
  typescript,
  tsconfig: './tsconfig.json'
 }),
 json(),
 terser()
 ]
}

export default defaultConfig

实现一个简单的 cli

在根目录创建一个 src 文件夹,然后再创建一个 index.ts

添加引用

添加引用并实例化 Command 对象。

import { Command } from 'commander'
import pkg from '../package.json'

const program = new Command(pkg.name)

自定义命令

实现一个可交互的自定义命令,模拟在终端(命令行)的登录功能。使用 command 方法创建一个命令,description 可以用来描述这个命令的作用,登录处理逻辑则写在 action 方法里。最后使用 parse(process.argv) 方法,解析命令。更多详细介绍和使用,可移步:https://github.com/tj/commander.js/blob/master/Readme_zh-CN.md。

program
 .command('login')
 .description('模拟登录。')
 .action(() => {
  handleLogin()
 })

program.parse(process.argv)

交互的话,用到前面说的 inquirer 库,接收输入的用户名和密码。选项的 type 的值有 inputpasswordnumbercheckboxeditorlistrawListexpandconfirm,选项 nameinquirer.prompt 方法返回的对象,选项 validate 可用来验证输入是否符合规则。更多详细介绍和使用,可移步:https://github.com/SBoudrias/Inquirer.js/blob/master/README.md

如果选项 typepassword,可通过 mask 设置掩码。

const handleLogin = () => {
 // 配置交互的用户名和密码
 const prompt = [
 {
  type: 'input',
  name: 'userName',
  message: '用户名:',
  validate: (value: string) => value.length > 0 || '用户名不能为空'
 },
 {
  type: 'password',
  name: 'password',
  message: '密码:',
  mask: '? ',
  validate: (value: string) => value.length > 0 || '密码不能为空'
 }
 ]

 inquirer.prompt(prompt).then(({ userName, password }) => {
 if (userName === 'demo' || password === '123456') {
  console.log('登录成功')
  return
 }
 console.log('用户名或密码错误')
 })
}

其他

一个 cli 工具,帮助信息也是必须的,可以通过 on('--help') 修改自定义帮助信息。

必须在 parse 方法之前。

program.on('--help', () => {
 console.log('\n运行 cli-demo -h | --help 查看命令使用。\n')
})

然后再来修改一下,没有输入任何参数的时候,会出现错误,可以使用 exitOverride 方法重新退出,在终端(命令行)输出帮助信息。

program.exitOverride()

try {
 program.parse(process.argv)
} catch (error) {
 program.outputHelp()
}

到这里,一个简单的 cli 工具完成了,先本地来测试下看看。在终端(命令行)输入 npm link,生成一个全局软连接,可以方便调试和测试。

使用typescript快速开发一个cli的实现示例

到此这篇关于使用typescript快速开发一个cli的实现示例的文章就介绍到这了,更多相关typescript开发cli内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
用 JSON 处理缓存
Apr 27 Javascript
jquery 多级下拉菜单核心代码
May 21 Javascript
需要做特殊处理的DOM元素属性的访问
Nov 05 Javascript
Jquery显示、隐藏元素以及添加删除样式
Aug 09 Javascript
js模拟点击以提交表单为例兼容主流浏览器
Nov 29 Javascript
点击button获取text内容并改变样式的js实现
Sep 09 Javascript
javascript实现日期三级联动下拉框选择菜单
Dec 03 Javascript
React Native基础入门之初步使用Flexbox布局
Jul 02 Javascript
javascript数组常见操作方法实例总结【连接、添加、删除、去重、排序等】
Jun 13 Javascript
浅谈JavaScript中的“!!”作用
Aug 03 Javascript
vue首次渲染全过程
Apr 21 Vue.js
JavaScript原始值与包装对象的详细介绍
May 11 Javascript
ES6中的类(Class)示例详解
Dec 09 #Javascript
JavaScript实现表单验证功能
Dec 09 #Javascript
element中Steps步骤条和Tabs标签页关联的解决
Dec 08 #Javascript
javascript全局自定义鼠标右键菜单
Dec 08 #Javascript
javascript局部自定义鼠标右键菜单
Dec 08 #Javascript
JavaScript对象访问器Getter及Setter原理解析
Dec 08 #Javascript
Vue+element-ui添加自定义右键菜单的方法示例
Dec 08 #Vue.js
You might like
正则表达式语法
2006/10/09 Javascript
php中注册器模式类用法实例分析
2015/11/03 PHP
做网页的一些技巧
2007/02/01 Javascript
jQuery的实现原理的模拟代码 -4 重要的扩展函数 extend
2010/08/03 Javascript
JavaScript中的slice()方法使用详解
2015/06/06 Javascript
javascript实现多栏闭合展开式广告位菜单效果实例
2015/08/05 Javascript
Boostrap模态窗口的学习小结
2016/03/28 Javascript
Angularjs 实现一个幻灯片示例代码
2016/09/08 Javascript
jQuery实现ajax无刷新分页页码控件
2017/02/28 Javascript
实例详解display:none与visible:hidden的区别
2017/03/30 Javascript
基于jQuery的左滑出现删除按钮的示例
2017/08/29 jQuery
JavaScrip数组删除特定元素的几种方法总结
2017/09/06 Javascript
原生js实现仿window10系统日历效果的实例
2017/10/31 Javascript
详解vue通过NGINX部署在子目录或者二级目录实践
2018/09/03 Javascript
babel7.x和webpack4.x配置vue项目的方法步骤
2019/05/12 Javascript
js 将线性数据转为树形的示例代码
2019/05/28 Javascript
JS实现从对象获取对象中单个键值的方法示例
2019/06/05 Javascript
在Node.js中将SVG图像转换为PNG,JPEG,TIFF,WEBP和HEIF格式的方法
2019/08/22 Javascript
javascript canvas封装动态时钟
2020/09/30 Javascript
Python Sleep休眠函数使用简单实例
2015/02/02 Python
在Django的视图中使用数据库查询的方法
2015/07/16 Python
Python中文竖排显示的方法
2015/07/28 Python
简述Python中的进程、线程、协程
2016/03/18 Python
Python排序搜索基本算法之希尔排序实例分析
2017/12/09 Python
python爬取网页内容转换为PDF文件
2020/07/28 Python
Python切片操作深入详解
2018/07/27 Python
Python实现字典排序、按照list中字典的某个key排序的方法示例
2018/12/18 Python
对python 自定义协议的方法详解
2019/02/13 Python
int在python中的含义以及用法
2019/06/27 Python
使用Python操作ArangoDB的方法步骤
2020/02/02 Python
详解pytorch中squeeze()和unsqueeze()函数介绍
2020/09/03 Python
检测浏览器是否支持html5视频的代码
2013/03/28 HTML / CSS
中学教师自我鉴定
2014/02/07 职场文书
2015年党日活动总结范文
2015/03/25 职场文书
2015年基层党建工作汇报材料
2015/06/25 职场文书
Java 中的 Lambda List 转 Map 的多种方法详解
2022/07/07 Java/Android