使用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 相关文章推荐
javascript延时重复执行函数 lLoopRun.js
Jun 29 Javascript
jQuery ui1.7 dialog只能弹出一次问题
Aug 27 Javascript
jquery实现微博文字输入框 输入时显示输入字数 效果实现
Jul 12 Javascript
使用jQuery快速解决input中placeholder值在ie中无法支持的问题
Jan 02 Javascript
当滚动条滚动到页面底部自动加载增加内容的js代码
May 13 Javascript
jQuery使用append在html元素后同时添加多项内容的方法
Mar 26 Javascript
JS基础随笔(菜鸟必看篇)
Jul 13 Javascript
原生JS获取元素集合的子元素宽度实例
Dec 14 Javascript
使用jQuery实现动态添加小广告
Jul 11 jQuery
利用js实现简易红绿灯
Oct 15 Javascript
利用 JavaScript 构建命令行应用
Nov 17 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
php curl模拟post请求小实例
2013/11/13 PHP
php使用qr生成二维码的示例分享
2014/01/20 PHP
PHP下的Oracle客户端扩展(OCI8)安装教程
2014/09/10 PHP
php.ini中date.timezone设置详解
2016/11/20 PHP
[原创]PHP获取数组表示的路径方法分析【数组转字符串】
2017/09/01 PHP
PHP开发中解决并发问题的几种实现方法分析
2017/11/13 PHP
php 根据URL下载远程图片、压缩包、pdf等文件到本地
2019/07/26 PHP
ExtJS 2.0实用简明教程 之获得ExtJS
2009/04/29 Javascript
JavaScript.The.Good.Parts阅读笔记(二)作用域&闭包&减缓全局空间污染
2010/11/16 Javascript
关于js获取radio和select的属性并控制的代码
2011/05/12 Javascript
js解析xml字符串和xml文档实现原理及代码(针对ie与火狐)
2013/02/02 Javascript
使用node+vue.js实现SPA应用
2016/01/28 Javascript
基于jquery插件实现拖拽删除图片功能
2020/08/27 Javascript
在js代码拼接dom对象到页面上去的模板总结(必看)
2017/02/14 Javascript
canvas实现简易的圆环进度条效果
2017/02/28 Javascript
JS 组件系列之Bootstrap Table 冻结列功能IE浏览器兼容性问题解决方案
2017/06/30 Javascript
vue.js开发实现全局调用的MessageBox组件实例代码
2017/11/22 Javascript
浅谈React前后端同构防止重复渲染
2018/01/05 Javascript
JavaScript的Proxy可以做哪些有意思的事儿
2019/06/15 Javascript
[02:17]TI4西雅图DOTA2前线报道 啸天mik夫妻档解说
2014/07/08 DOTA
Python ORM框架SQLAlchemy学习笔记之安装和简单查询实例
2014/06/10 Python
Python中实现从目录中过滤出指定文件类型的文件
2015/02/02 Python
Pycharm学习教程(2) 代码风格
2017/05/02 Python
python求质数的3种方法
2018/09/28 Python
pandas 选取行和列数据的方法详解
2019/08/08 Python
Python计算机视觉里的IOU计算实例
2020/01/17 Python
html5 Canvas画图教程(4)—未闭合的路径及渐变色的填充方法
2013/01/09 HTML / CSS
美国生日蛋糕店:Bake Me A Wish!
2017/02/08 全球购物
为您的家、后院、车库等在线购物:Spreetail
2019/06/17 全球购物
修理厂厂长岗位职责
2014/01/30 职场文书
远程研修随笔感言
2014/02/10 职场文书
车队司机自我鉴定
2014/03/02 职场文书
幼儿园小班评语
2014/04/18 职场文书
离婚财产处理协议书
2014/09/30 职场文书
vue组件的路由高亮问题解决方法
2021/05/11 Vue.js
Python图片处理之图片裁剪教程
2021/05/27 Python