CLI
CLI 相关库
ufo ---> 功能丰富的URL处理
用法多样,解决大多数URL处理问题。包括提取内容、替换内容、判断内容等。
import { parseURL, withQuery, ... } from 'ufo'
// Result: { protocol: 'http:', auth: '', host: 'foo.com', pathname: '/foo', search: '?test=123', hash: '#token' }
parseURL('http://foo.com/foo?test=123#token')
// Result: /foo?page=a&token=secret
withQuery('/foo?page=a', { token: 'secret' })
// Result: { test: '123', unicode: '好' }
getQuery('http://foo.com/foo?test=123&unicode=%E5%A5%BD')
// Result: true
isSamePath('/foo', '/foo/')
// Result: http://example.com
withHttp('https://example.com')del ---> glob匹配删除文件
import del from 'del'
(async () => {
const deletedFilePaths = await del(['temp/*.js', '!temp/unicorn.js']);
const deletedDirectoryPaths = await del(['temp', 'public']);
console.log('Deleted files:\n', deletedFilePaths.join('\n'));
console.log('\n\n');
console.log('Deleted directories:\n', deletedDirectoryPaths.join('\n'));
})();conventional-changelog-cli ---> 自动生成日志
根据git记录,生成CHANGELOG.md日志
$ npm i conventional-changelog-cli -g
$ conventional-changelog -p angular -i CHANGELOG.md -sminimist ---> 解析命令行参数
var argv = require('minimist')(process.argv.slice(2));
console.log(argv);$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
{ _: [ 'foo', 'bar', 'baz' ],
x: 3,
y: 4,
n: 5,
a: true,
b: true,
c: true,
beep: 'boop' }trash ---> 移动文件到回收站
不同于rimraf/del,trash只是将文件移动到回收站,而不是删除。
import trash from 'trash';
await trash(['*.png', '!rainbow.png']);data-fns ---> 日期操作库
操作包括,给日期做加减法、找出最靠近某个日期的日期等等,还有最重要的支持i18n的格式化:
const { formatDistance, subDays } = require('date-fns')
const { zhCN } = require('date-fns/locale')
console.log(formatDistance(new Date('2022-05-26'), new Date(), { addSuffix: true, locale: zhCN }))
// 大约 16 小时前
console.log(formatDistance(new Date('2022-05-20'), new Date(), { addSuffix: true, locale: zhCN }))
// 7 天前tiny-glob ---> 高效的文件glob匹配
import glob from 'tiny-glob'
(async() => {
let files = await glob('test/*/*.{js,md}');
console.log(files)
//=> [ 'test/README.md', 'test/webpack.config.js' ]
})()相似项目:mrmlnc/fast-glob、sindresorhus/globby 、isaacs/node-glob
文件无关:isaacs/minimatch、isaacs/pico
mkdist ---> file-to-file transpiler
$ npx mkdist
resolve-from ---> 像 require.resolve() 但是指定 from
另一个类似的包,但是查询全局 sindresorhus/resolve-global
const resolveFrom = require('resolve-from');
// There is a file at `./foo/bar.js`
resolveFrom('foo', './bar');
//=> '/Users/sindresorhus/dev/test/foo/bar.js'local—pkg ---> 获取本地包的信息
import {
getPackageInfo, importModule, isPackageExists, resolveModule,
} from 'local-pkg'
isPackageExists('local-pkg') // true
isPackageExists('foo') // false
await getPackageInfo('local-pkg')
/* {
* name: "local-pkg",
* version: "0.1.0",
* rootPath: "/path/to/node_modules/local-pkg",
* packageJson: {
* ...
* }
* }
*/
// similar to `require.resolve` but works also in ESM
resolveModule('local-pkg')
// '/path/to/node_modules/local-pkg/dist/index.cjs'
// similar to `await import()` but works also in CJS
const { importModule } = await importModule('local-pkg')is-installed-globally ---> 判断当前包是否是全局安装
如果您的 CLI 在全局和本地安装时需要不同的行为,这会很有用。
import isInstalledGlobally from 'is-installed-globally';
// With `npm install your-package`
console.log(isInstalledGlobally);
//=> false
// With `npm install --global your-package`
console.log(isInstalledGlobally);
//=> truecli-progress ---> 在终端中显示进度
const cliProgress = require('cli-progress');
// create a new progress bar instance and use shades_classic theme
const bar1 = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
// start the progress bar with a total value of 200 and start value of 0
bar1.start(200, 0);
// update the current value in your application..
bar1.update(100);
// stop the progress bar
bar1.stop();concurrently ---> 同时执行多个scripts命令
支持命令行使用:
$ npm i concurrently -g
$ concurrently "command1 arg" "command2 arg"或者在脚本中使用:
{
"scripts": {
"start": "concurrently \"npm run dev\" \"npm run build\"",
}
}commitizen ---> 规范 commit 信息
安装和配置:
➜ npm install -g commitizen
➜ commitizen init cz-conventional-changelog --pnpm --save-dev --save-exact使用:
$ git add .
$ git cz
cz-cli@4.3.0, cz-conventional-changelog@3.3.0
? Select the type of change that you're committing: (Use arrow keys)
❯ feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing tests or correcting existing testsnpm-run-all ---> 并行执行多个脚本
包含命令 npm-run-all、run-p、run-s
run-s:相当于npm-run-all -s,依次执行(sequential),类似pnpm clean && pnpm build && pnpm lintrun-p:相当于npm-run-all -s,并行执行(parallel)
is-ci ---> 判断代码运行环境是否为命令行
可以在 package.json 中这样使用
{
"scripts": {
"prepare": "is-ci || husky install",
}
}lint-staged ---> 针对暂存文件运行 linters
配合 toplenboren/simple-git-hooks,实现在 commit 之前执行代码检查
{
"simple-git-hooks": {
"pre-commit": "npx lint-staged"
},
"lint-staged": {
"*.ts": "eslint",
"*.md": "prettier --list-different"
}
}changelogen ---> CHANGELOG 生成工具
还支持 bump 命令发版
$ npx changelogen@latest
$ npx changelogen@latest --bump
just ---> command runner
just 有大量有用的功能,并且比 make 进行了许多改进,使用 rust 编写。
brew install justjustfile 文件示例
build:
cc *.c -o main
test-all: build
./test --all使用
$ just test-all
cc *.c -o main
./test --all
Yay, all your tests passed!open ---> 打开一切
import open from 'open'
await open('./dog.png') // 默认的图片查看器打开
await open('./index.ts') // 默认的编辑器打开
await open('https://peterroe.icu') // 默认浏览器打开网页
await open('https://peterroe.icu', { app: { name: 'firefox' }) // firefox打开
await open('xcode') // 打开一个软件debug ---> 埋点调试
通过设置环境变量,灵活选择调试的模块
var a = require('debug')('worker:a')
, b = require('debug')('worker:b');
function work() {
a('doing lots of uninteresting work');
setTimeout(work, Math.random() * 1000);
}
work();
function workb() {
b('doing some work');
setTimeout(workb, Math.random() * 2000);
}
workb();$ DEBUG=worker:* node index.js
$ DEBUG=worker:b node index.jscac ---> 命令行参数解析工具
如果你想开发一款命令行工具,试试它
const cli = require('cac')()
cli
.command('build <entry> [...otherFiles]', 'Build your app')
.option('--foo', 'Foo option')
.action((entry, otherFiles, options) => {
console.log(entry)
console.log(otherFiles)
console.log(options)
})
cli.help()
cli.parse()ink ---> 用 React 写命令行工具
挺有意思
import React, {useState, useEffect} from 'react';
import {render, Text} from 'ink';
const Counter = () => {
const [counter, setCounter] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCounter(previousCounter => previousCounter + 1);
}, 100);
return () => {
clearInterval(timer);
};
}, []);
return <Text color="green">{counter} tests passed</Text>;
};
render(<Counter />);listr ---> 终端列表任务 UI
用于展示执行任务的过程
const tasks = new Listr([
{
title: 'Success',
task: () => 'Foo'
},
{
title: 'Failure',
task: () => {
throw new Error('Bar')
}
}
]);boxen ---> 在终端中创建框
import boxen from 'boxen';
console.log(boxen('unicorn', {padding: 1}));
/*
┌─────────────┐
│ │
│ unicorn │
│ │
└─────────────┘
*/yargs ---> parse args for CLI
#!/usr/bin/env node
const yargs = require('yargs/yargs')
const { hideBin } = require('yargs/helpers')
const argv = yargs(hideBin(process.argv)).argv
if (argv.ships > 3 && argv.distance < 53.5) {
console.log('Plunder more riffiwobbles!')
} else {
console.log('Retreat from the xupptumblers!')
}clack ---> build beautiful prompt in cli
Two options:
- @clack/core: unstyled, extensible for CLIs
- @clack/prompts: beautiful, ready-to-use CLI prompt
import { isCancel, cancel, text } from '@clack/prompts';
const value = await text(/* TODO */);
if (isCancel(value)) {
cancel('Operation cancelled.');
process.exit(0);
}difftastic ---> Diff 命令行工具
$ brew install difftastic