CLI 交互优化(输入校验 + 覆盖目录确认)
扩展内容
本节优化 CLI 交互体验,添加 package name 的 NPM 规则校验和目标目录已存在时的覆盖确认。使用 prompts 库内置的 validate 功能实现输入校验。
NPM 包名校验
校验规则
NPM 包名需遵循以下规则:
- 只允许小写字母、数字、连字符(
-)和下划线(_) - 不能以
.或_开头 - 长度不超过 214 字符
- 不能包含大写字母或特殊字符
正则表达式
// NPM 包名校验正则
const npmNameRegex = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/
typescript
集成到 prompts
import prompts from 'prompts'
const response = await prompts({
type: 'text',
name: 'pkgName',
message: '项目名称:',
initial: 'my-project',
validate: (value: string) => {
if (!npmNameRegex.test(value)) {
return '项目名称不符合 npm 包规则,请使用英文小写'
}
return true // 返回 true 表示校验通过
},
})
typescript
校验逻辑
用户输入 → validate(value)
│
├── 返回 string(错误消息)→ 显示提示,重新输入
│
└── 返回 true → 校验通过,继续下一步
text
覆盖目录确认
检查目标目录是否已存在
import fs from 'fs-extra'
import path from 'path'
async function checkTargetDir(targetDir: string): Promise<boolean> {
if (await fs.pathExists(targetDir)) {
const { overwrite } = await prompts({
type: 'confirm',
name: 'overwrite',
message: `目标目录 ${targetDir} 已存在,是否覆盖?`,
initial: false,
})
return overwrite
}
return true
}
typescript
完整交互流程
async function createProject() {
// 1. 输入项目名称(带校验)
const { pkgName } = await prompts({
type: 'text',
name: 'pkgName',
message: '项目名称:',
validate: (value) =>
npmNameRegex.test(value) || '项目名称不符合 npm 包规则,请使用英文小写',
})
// 2. 检查目录覆盖
const targetDir = path.join(process.cwd(), pkgName)
const shouldContinue = await checkTargetDir(targetDir)
if (!shouldContinue) {
console.log('操作已取消')
process.exit(0)
}
// 3. 继续后续流程...
await processTemplates(pkgName, targetDir)
}
typescript
测试校验
# 测试不符合规则的名称
create-vp my-PROJECT # 提示:请使用英文小写
create-vp 123.project # 提示:不符合 npm 包规则
create-vp my-project # 校验通过,继续
bash
关键要点
prompts库内置validate函数,返回string为错误提示,返回true为通过- NPM 包名正则确保用户输入符合包命名规范
- 可借助 AI 工具生成正则表达式
- 覆盖目录确认使用
confirm类型的 prompt - 校验失败时给出友好的错误提示,引导用户正确输入
↑