node-uncli
v0.0.1
Published
A simple, fast, and visually appealing CLI tool library.
Maintainers
Readme
uncli
一个简单、快速、美观的 CLI 工具库
uncli 是一个现代化的 TypeScript CLI 工具库,它封装了 commander、inquirer、ora 和 chalk 等流行库,提供统一、简洁的 API 接口,让你能够快速构建美观的命令行应用。
✨ 特性
- 🚀 简单易用 - 提供直观的 API,隐藏底层库的复杂性
- 💪 类型安全 - 完整的 TypeScript 支持,提供编译时类型检查
- 🎨 美观输出 - 内置颜色、样式和加载动画支持
- 🔧 功能完整 - 命令管理、交互式提示、加载动画、样式输出一应俱全
- 📦 开箱即用 - 零配置,安装即用
- 🌳 Tree-shakable - 支持 ES Module,按需引入
📦 安装
npm install uncliyarn add unclipnpm add uncli🚀 快速开始
import { UnCli, prompt, createSpinner, style, PromptType } from 'uncli';
// 创建 CLI 应用
const cli = new UnCli('my-app', '1.0.0');
// 定义命令
cli.command({
name: 'init',
description: '初始化项目',
options: [
{
flags: '-t, --template <name>',
description: '模板名称',
defaultValue: 'default'
}
],
action: async (options) => {
// 使用交互式提示
const projectName = await prompt({
type: PromptType.Input,
message: '项目名称:',
default: 'my-project'
});
// 使用加载动画
const spinner = createSpinner({ text: '正在创建项目...' });
spinner.start();
// 模拟异步操作
await new Promise(resolve => setTimeout(resolve, 2000));
spinner.succeed('项目创建成功!');
// 使用样式输出
console.log(style.success('✓ 完成'));
console.log(style.info(`项目名称: ${projectName}`));
console.log(style.info(`使用模板: ${options.template}`));
}
});
// 解析命令行参数
cli.parse();📖 API 文档
命令管理
UnCli
创建 CLI 应用实例。
import { UnCli } from 'uncli';
const cli = new UnCli('app-name', '1.0.0');command(config)
注册一个命令。
cli.command({
name: 'build',
description: '构建项目',
options: [
{
flags: '-o, --output <path>',
description: '输出目录',
defaultValue: './dist'
},
{
flags: '-w, --watch',
description: '监听文件变化',
defaultValue: false
}
],
action: (options) => {
console.log(`构建到: ${options.output}`);
if (options.watch) {
console.log('监听模式已启用');
}
}
});parse(argv?)
解析命令行参数并执行匹配的命令。
// 解析默认的命令行参数
cli.parse();
// 解析自定义参数
cli.parse(['node', 'cli.js', 'build', '--output', './dist']);交互式提示
prompt(config)
显示交互式提示并获取用户输入。
文本输入
import { prompt, PromptType } from 'uncli';
const name = await prompt({
type: PromptType.Input,
message: '请输入您的名字:',
default: 'Anonymous',
validate: (input) => {
if (input.length < 2) {
return '名字至少需要 2 个字符';
}
return true;
}
});确认提示
const confirmed = await prompt({
type: PromptType.Confirm,
message: '确认继续吗?',
default: true
});单选列表
const framework = await prompt({
type: PromptType.List,
message: '选择一个框架:',
choices: [
'React',
'Vue',
'Angular',
{ name: 'Svelte (推荐)', value: 'svelte' }
]
});多选列表
const features = await prompt({
type: PromptType.Checkbox,
message: '选择需要的功能:',
choices: [
{ name: 'TypeScript', value: 'ts', checked: true },
{ name: 'ESLint', value: 'eslint', checked: true },
{ name: 'Prettier', value: 'prettier' },
{ name: 'Jest', value: 'jest' }
]
});密码输入
const password = await prompt({
type: PromptType.Password,
message: '请输入密码:',
validate: (input) => {
if (input.length < 6) {
return '密码至少需要 6 个字符';
}
return true;
}
});加载动画
createSpinner(config)
创建加载动画实例。
import { createSpinner } from 'uncli';
const spinner = createSpinner({
text: '正在加载...',
color: 'cyan',
spinner: 'dots'
});
// 启动动画
spinner.start();
// 更新文本
spinner.text('正在处理数据...');
// 成功结束
spinner.succeed('加载完成!');
// 失败结束
spinner.fail('加载失败!');
// 警告结束
spinner.warn('加载完成,但有警告');
// 信息结束
spinner.info('这是一条信息');
// 停止动画(不显示状态图标)
spinner.stop();Spinner 类
也可以直接使用 Spinner 类:
import { Spinner } from 'uncli';
const spinner = new Spinner({ text: '正在加载...' });
spinner.start();
// 执行异步操作
await someAsyncOperation();
spinner.succeed('完成!');样式输出
style
提供各种文本样式和颜色。
颜色
import { style } from 'uncli';
console.log(style.red('错误信息'));
console.log(style.green('成功信息'));
console.log(style.yellow('警告信息'));
console.log(style.blue('提示信息'));
console.log(style.magenta('品红色文本'));
console.log(style.cyan('青色文本'));
console.log(style.white('白色文本'));
console.log(style.gray('灰色文本'));文本样式
console.log(style.bold('粗体文本'));
console.log(style.italic('斜体文本'));
console.log(style.underline('下划线文本'));
console.log(style.strikethrough('删除线文本'));语义化样式
console.log(style.success('✓ 操作成功'));
console.log(style.error('✗ 操作失败'));
console.log(style.warning('⚠ 警告信息'));
console.log(style.info('ℹ 提示信息'));组合样式
const boldRed = style.combine(style.bold, style.red);
console.log(boldRed('重要错误'));
const underlineBlue = style.combine(style.underline, style.blue);
console.log(underlineBlue('链接文本'));错误处理
uncli 提供了统一的错误类型:
import {
UnCliError,
ValidationError,
CommandError,
UserCancelError
} from 'uncli';
try {
// 你的代码
} catch (error) {
if (error instanceof ValidationError) {
console.error('参数验证失败:', error.message);
} else if (error instanceof CommandError) {
console.error('命令执行失败:', error.message);
} else if (error instanceof UserCancelError) {
console.log('用户取消了操作');
} else if (error instanceof UnCliError) {
console.error('uncli 错误:', error.message);
}
}🎯 完整示例
#!/usr/bin/env node
import { UnCli, prompt, createSpinner, style, PromptType } from 'uncli';
const cli = new UnCli('project-cli', '1.0.0');
// 初始化命令
cli.command({
name: 'init',
description: '初始化新项目',
action: async () => {
console.log(style.bold('\n🚀 创建新项目\n'));
// 收集项目信息
const projectName = await prompt({
type: PromptType.Input,
message: '项目名称:',
validate: (input) => {
if (!input) return '项目名称不能为空';
if (!/^[a-z0-9-]+$/.test(input)) {
return '项目名称只能包含小写字母、数字和连字符';
}
return true;
}
});
const framework = await prompt({
type: PromptType.List,
message: '选择框架:',
choices: ['React', 'Vue', 'Angular', 'Svelte']
});
const features = await prompt({
type: PromptType.Checkbox,
message: '选择功能:',
choices: [
{ name: 'TypeScript', value: 'typescript', checked: true },
{ name: 'ESLint', value: 'eslint', checked: true },
{ name: 'Prettier', value: 'prettier' },
{ name: 'Jest', value: 'jest' }
]
});
const useGit = await prompt({
type: PromptType.Confirm,
message: '初始化 Git 仓库?',
default: true
});
// 创建项目
const spinner = createSpinner({ text: '正在创建项目...', color: 'cyan' });
spinner.start();
// 模拟项目创建过程
await new Promise(resolve => setTimeout(resolve, 1000));
spinner.text('正在安装依赖...');
await new Promise(resolve => setTimeout(resolve, 1500));
if (useGit) {
spinner.text('正在初始化 Git...');
await new Promise(resolve => setTimeout(resolve, 500));
}
spinner.succeed('项目创建成功!');
// 显示项目信息
console.log('\n' + style.bold('项目信息:'));
console.log(style.gray('─'.repeat(40)));
console.log(`${style.cyan('名称:')} ${projectName}`);
console.log(`${style.cyan('框架:')} ${framework}`);
console.log(`${style.cyan('功能:')} ${features.join(', ')}`);
console.log(`${style.cyan('Git:')} ${useGit ? '是' : '否'}`);
console.log(style.gray('─'.repeat(40)));
console.log('\n' + style.success('✓ 完成!'));
console.log('\n' + style.bold('下一步:'));
console.log(` ${style.gray('$')} cd ${projectName}`);
console.log(` ${style.gray('$')} npm install`);
console.log(` ${style.gray('$')} npm run dev\n`);
}
});
// 构建命令
cli.command({
name: 'build',
description: '构建项目',
options: [
{
flags: '-m, --mode <mode>',
description: '构建模式',
defaultValue: 'production'
},
{
flags: '-w, --watch',
description: '监听文件变化',
defaultValue: false
}
],
action: async (options) => {
console.log(style.bold(`\n📦 构建项目 (${options.mode})\n`));
const spinner = createSpinner({ text: '正在构建...', color: 'green' });
spinner.start();
// 模拟构建过程
await new Promise(resolve => setTimeout(resolve, 2000));
spinner.succeed('构建完成!');
if (options.watch) {
console.log(style.info('\n👀 监听文件变化中...'));
}
}
});
// 解析命令
cli.parse();🔧 开发
# 安装依赖
npm install
# 构建
npm run build
# 运行测试
npm test
# 生成覆盖率报告
npm run test:coverage
# 监听模式
npm run test:watch📝 许可证
MIT
