【日常记录】【node】从零开发一个node命令行工具

1、命令行工具

命令行工具(Cmmand Line Interface)简称cli,顾名思义就是在命令行终端中使用的工具。我们常用的 git 、npm、vim 等都是 cli 工具,比如我们可以通过 git clone 等命令简单把远程代码复制到本地。

再比如:vue的 vue-cli ;acro 的 arco-cli;vite的 npm create vite@latest ;nest 的 nest-cli等等

2、如何开发一个 node 命令行工具

2.1、初始化项目

  1. 创建一个文件夹,执行 npm 初始化命令
npm init -y
  1. 创建 src 文件夹,然后创建 index.js 文件,并写入以下代码
#!/usr/bin/env nodeconsole.log("hello world!");

里面的第一行代码,是告诉终端,这个文件要使用 node 去执行。具体含义需要百度了

2.2、本地创建命令

一般 cli都有一个特定的命令,比如 node、npm、pnpm、nest、arco 等等,所以我们也要给这个工具设置一个命令,比如 ncr

需要修改 package.json 文件 , 要加上 bin 这个属性,值是对象, 对象里面是 键值对 ,键是 命令名称,值是 入口文件路径

{"name": "ncr","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"bin": {"ncr": "./src/index.js"},"keywords": [],"author": "","license": "ISC"
}

然后 还需要再根目录执行一下 npm link , 有下面这个输出就对了

在这里插入图片描述

然后 终端 执行 ncr ,可以看到 hello world 就对了

在这里插入图片描述

2.3 实现获取版本信息命令 commander

如若再终端,输入 ncr -v --version ,我们想获取到 当前工具版本

先修改 src/index.js

#!/usr/bin/env nodeconsole.log("hello world!");
console.log(process.argv);

在这里插入图片描述

process.argv 这个属性的返回值,是数组,数组的第二项往后,就是 用户输入的命令

commander 这个库,可以解析命令行的参数,一般再开发命令行工具的时候,都会用这个

npm i commander
#!/usr/bin/env nodeconst pkg = require("../package.json");
const { program } = require("commander"); // 解析 命令行 参数的库// 设置 -h 选项的 用法
program.name("ncr").usage("[options]");
// program.version(pkg.version, "-v, --version", "获取 ncr 版本");// 添加选项
program.option("-v, --version", "获取 ncr 版本");
program.option("-h, --help", "获取帮助信息");// 处理选项
program.action(() => {let options = program.opts();console.log("option 获取");if (options.help) {console.log(`███╗   ██╗ ██████╗██████╗ ████╗  ██║██╔════╝██╔══██╗██╔██╗ ██║██║     ██████╔╝██║╚██╗██║██║     ██╔══██╗██║ ╚████║╚██████╗██║  ██║╚═╝  ╚═══╝ ╚═════╝╚═╝  ╚═╝
`);console.log(program.helpInformation());console.log("---------------------------------------------------------------------------------------");console.log("欢迎使用~~~~~");console.log("---------------------------------------------------------------------------------------");} else if (options.version) {console.log(chalk.blue.bgMagenta.bold(`当前版本号是: ${pkg.version}`));}
});

这个时候再终端输入 ncr -h 就会看到以下结果

在这里插入图片描述

Usage: index [options] 这一段也是可以修改的;Usage 就是用法的意思

program.name("ncr").usage("[options]");

在这里插入图片描述

2.4、终端输出增加颜色

需要用到 chalk 这个库

npm install chalk
const chalk = require("chalk"); // 让终端输出 增加一些样式
console.log(chalk.blue.bgMagenta.bold(`当前版本号是: ${pkg.version}`));

在这里插入图片描述

终端输入 ncr -v 终端报错

const chalk = require("chalk"); // 让终端输出 增加一些样式^Error [ERR_REQUIRE_ESM]: require() of ES Module F:\个人项目\ncr\node_modules\chalk\source\index.js from F:\个人项目\ncr\src\index.js not supported.
Instead change the require of F:\个人项目\ncr\node_modules\chalk\source\index.js in F:\个人项目\ncr\src\index.js to a dynamic import() which is available in all CommonJS modules.   at Object.<anonymous> (F:\个人项目\ncr\src\index.js:5:15) {code: 'ERR_REQUIRE_ESM'
}

在这里插入图片描述

如若出现这个错误,就降低 chalk的版本,换成 4 版本的

2.5、ncr current 命令 代码编写

// index.js
const { getRegistry } = require("./utils");program.command("current").description("查看当前npm镜像源").action(() => {console.log("当前npm镜像源是: " + chalk.blue.bgMagenta.bold(`${getRegistry()}`));});
// src/util/index.js
const { exec, execSync } = require("child_process"); //子线程用于执行shell命令exports.getRegistry = function () {// 默认返回 buffer 格式,return execSync("npm get registry", { encoding: "utf-8" });
};

在这里插入图片描述

2.6、ncr list 命令代码编写

registry.json

{"npm": {"registry": "https://registry.npmjs.org/","ping": "https://registry.npmjs.org/"},"yarn": {"registry": "https://registry.yarnpkg.com/","ping": "https://registry.yarnpkg.com/"},"taobao": {"registry": "https://registry.npmmirror.com/","ping": "https://registry.npmmirror.com/"}
}

// 查看所有的 npm 镜像源
const registryList = require("./registry.json");program.command("list").alias("ls") // 起个别名,也可以用 aliases方法,传递一个数组,设置多个别名.description("查看所有的npm镜像源").action(async () => {let curRegistry = getRegistry();Object.entries(registryList).forEach((f) => {console.log(// 一定要加 trim(f[1].registry.trim() === curRegistry.trim()? chalk.blue.bgMagenta.bold("*"): " ") +" " +f[0].padEnd(15, "-") +" " +f[1].registry);});});

2.7、ncr use 命令代码编写

切换源

// 使用某个 npm 镜像源const inquirer = require("inquirer"); // 交互式命令工具program.command("use").description("切换npm镜像源").action(() => {inquirer.prompt([{type: "list",name: "select",message: "请选择npm镜像源",choices: Object.keys(registryList).map((f) => f),},]).then((res) => {// res { select: 'yarn' }let registryUrl = registryList[res.select].registry;exec(`npm config set registry ${registryUrl}`,(error, stdout, stderr) => {if (error) {console.error(`exec error: ${error}`);return;}console.log("切换成功!");});});});

在这里插入图片描述

3、发布npm

先把npm的 registry 切换到官方的镜像源

npm login 先登录一下

然后 执行 npm publish

403 错误,大多数情况是 包的name 重名了

在这里插入图片描述

这样就是成功了!

总结

解析命令行的工具

  1. Yargs
  2. yargs-parser
  3. arg
  4. minimist
  5. commander

参考链接

  • chalk GitHub文档
  • inquirer GitHub文档
  • commander GitHub文档
  • node api

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/27397.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我是计算机专业的学生,请帮我分析“程序,进程,线程,超线程“之间的联系和区别。

程序、进程、线程、超线程之间的联系与区别分析如下&#xff1a; 一、程序 定义&#xff1a;程序是一组指令的集合&#xff0c;用于描述完成特定任务的步骤和操作。它通常以源代码的形式编写&#xff0c;并使用编程语言如C、Java、Python等来表示。程序本身是静态的&#xff…

记录一些互联网实习面经

1 地平线 视觉工程师 1、问每个项目&#xff0c;比如yolo 检测用到的损失函数是什么&#xff1f; 2、训练过程中loss出现nan怎么办&#xff1f;解决方法&#xff1f; 3、训练过程中&#xff0c;训练和验证torch的parameter&#xff1f; 4、项目中用到的分割方法是什么&#xf…

Apache druid未授权命令执行漏洞复现

简介 Apache Druid是一个实时分析型数据库&#xff0c;旨在对大型数据集进行快速的查询分析&#xff08;"OLAP"查询)。Druid最常被当做数据库来用以支持实时摄取、高性能查询和高稳定运行的应用场景&#xff0c;同时&#xff0c;Druid也通常被用来助力分析型应用的图…

QVector使用详解

QVector使用详解 一、 创建和初始化1. 默认构造函数2. 指定大小的构造函数3. 指定大小和初始值的构造函数4. 使用 std::initializer_list 初始化5. 拷贝构造函数6. 从指针和大小初始化7. 使用 std::vector 初始化8. 使用 QList 初始化9. 使用 QVector 初始化 QList10. 使用 fil…

力扣2861.最大合金数

力扣2861.最大合金数 对每一台机器都做一次二分答案 class Solution {public:int maxNumberOfAlloys(int n, int k, int budget, vector<vector<int>>& composition, vector<int>& stock, vector<int>& cost) {int res 0;int mx rang…

5款好用的轻量云服务器(618超便宜轻量云)

轻量云服务器是一种面向入门级用户和小型业务的云服务器产品&#xff0c;它们通常价格更实惠&#xff0c;管理起来也相对简单&#xff0c;以下是五款好用的轻量云服务器产品&#xff1a; 1.阿里云 优势&#xff1a;阿里云是国内最大的云服务提供商之一&#xff0c;拥有丰富的配…

二 分 模 板

bool check(int x) {/* ... */} // 检查x是否满足某种性质// 区间[l, r]被划分成[l, mid]和[mid 1, r]时使用&#xff1a; int bsearch_1(int l, int r) {while (l < r){int mid l r >> 1;if (check(mid)) r mid; // check()判断mid是否满足性质else l mid 1…

BT音频方案

一、缩写 缩写 全程 释义 I2S I2S 音频传输接口总线 PCM Pulse-Code Modulation 基础音频数据或翻译为音频接口总线 HFP Handsfree 蓝牙通话协议 A2DP Advanced Audio Distribution Profile 蓝牙媒体音频协议 二、音频流转策略 蓝牙音频功能分为通话声音和媒体…

电脑数字键被锁住不能输入数字

情况: 反复点击数字键盘的NumLock,看它的灯是否能正常启动 1.如果NumLock灯可以正常的打开和关闭,并且无法输入内容 1.1打开控制面板 1.2 进入轻松使用中选择更改键盘的工作方式 1.3找到并点击设置鼠标键 1.4 赵到NumLock设置为关闭,然后确定即可

线性规划问题——单纯形算法

第一步&#xff1a;化“约束标准型” 在每个等式约束中至少有一个变量的系数为正&#xff0c;且这个变量只在该约束中出现。在每个约束方程中选择一个这样的变量称为基本变量。 剩下变量称为非基本变量。 一个简单的栗子 上图是一个约束标准型线性规划的例子。 等式1&#x…

理解查准率P、查全率R及Fβ度量怎么得来的

如果得到的是一组样本在两个算法上的一次预测结果&#xff0c;其中每个样本都被赋予了一个为正样本的概率&#xff08;例如&#xff0c;通过逻辑回归或朴素贝叶斯分类器得到的概率估计&#xff09;&#xff0c;那么可以通过改变不同的阈值点来利用这些预测结果画出PR曲线。 如果…

blender

通用设置: 仅显示/取消隐藏:数字键盘/移动视角:shift+鼠标中键Blender如何给场景添加参考图片-百度经验 (baidu.com)进入编辑模式:Tab编辑模式:点-线-面 反选:ctrl+按键重新计算面朝向:shift+n水密:+修改器:焊接连选的区别: 视窗设置 两个视图 …

Pytorch环境配置的方法

Pytorch虚拟环境配置全流程 以安装pytorch1.9.1为例 1. 创建虚拟环境 安装Anaconda3&#xff0c;打开 PowerShell 创建虚拟环境并进入&#xff1a; conda create -n torch1.9.1 python3.8 conda activate torch1.9.1 conda create -n torch1.9.1 python3.8 conda activate to…

Python - 处理电子书的库

kindleunpack&#xff1a; 转换azw3为epub https://github.com/kevinhendricks/KindleUnpackkindlegen 转换epub为mobiOpenBookPublishers https://github.com/orgs/OpenBookPublishers/repositories?qsort%3Astarsepub2pdf : converting fixed-layout manga/comic files(epub…

实验室中几种电机性能比较与LabVIEW控制介绍

本文从精度、稳定性、速度、负载能力、兼容性等角度对PI闭环步进电机、PI压电陶瓷、Newport SMC100、Newport 8743/8742、Nator x/y/z rotation五种设备进行详细比较&#xff0c;并结合LabVIEW软件开发&#xff0c;提出控制建议&#xff0c;旨在优化电机控制系统&#xff0c;提…

错题记录(小测)

单选 错题1 错题2 错题3 代码题 反转链表 链表的回文结构

【LeetCode】4,寻找两个正序数组中的中位数

题目地址 B站那个官方解答视频实在看不懂&#xff0c;我就根据他那个代码和自己的理解写一篇文章 1. 基本思路 在只有一个有序数组的时候&#xff0c;中位数把数组分割成两个部分。中位数的定义&#xff1a;中位数&#xff0c;又称中点数&#xff0c;中值。中位数是按顺序排列…

消息队列的应用场景有哪些

通常来说&#xff0c;使用消息队列主要能为我们的系统带来下面三点好处&#xff1a; 异步处理 削峰/限流 降低系统耦合性 除了这三点之外&#xff0c;消息队列还有其他的一些应用场景&#xff0c;例如实现分布式事务、顺序保证和数据流处理。 异步处理 通过异步处理提高系…

计算机网络:网络层 - IPv4数据报 ICMP协议

计算机网络&#xff1a;网络层 - IPv4数据报 & ICMP协议 IPv4数据报[版本 : 首部长度 : 区分服务 : 总长度][标识 : 标志 : 片偏移][生存时间 : 协议 : 首部检验和][可变部分 : 填充字段] ICMP协议 IPv4数据报 一个IPv4数据报&#xff0c;由首部和数据两部分组成&#xff…