Skip to content
0

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 -s

minimist ---> 解析命令行参数

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/deltrash只是将文件移动到回收站,而不是删除。

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-globsindresorhus/globbyisaacs/node-glob

文件无关:isaacs/minimatchisaacs/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);
//=> true

cli-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 tests

npm-run-all ---> 并行执行多个脚本

包含命令 npm-run-allrun-prun-s

  • run-s:相当于 npm-run-all -s,依次执行(sequential),类似 pnpm clean && pnpm build && pnpm lint
  • run-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 just

justfile 文件示例

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.js

cac ---> 命令行参数解析工具

如果你想开发一款命令行工具,试试它

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:

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

Released under the MIT License.