UNPKG

@aiwanna-team/repo-start

Version:

一个交互式的项目模板选择和初始化CLI工具

145 lines (144 loc) 5.32 kB
#!/usr/bin/env node import { Command } from "commander"; import inquirer from "inquirer"; import chalk from "chalk"; import ora from "ora"; import { execSync } from "child_process"; import { readFileSync } from "fs"; import { fileURLToPath } from "url"; import { dirname, join } from "path"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const templatesPath = join(__dirname, "../templates.json"); let templates; try { const templatesData = readFileSync(templatesPath, "utf8"); templates = JSON.parse(templatesData); } catch (error) { console.error(chalk.red("❌ 无法读取模板配置文件")); console.error(error); process.exit(1); } const packagePath = join(__dirname, "../package.json"); let version = "0.0.0"; try { const packageData = readFileSync(packagePath, "utf8"); const packageJson = JSON.parse(packageData); version = packageJson.version; } catch (error) { console.warn(chalk.yellow("⚠️ 无法读取package.json,使用默认版本号")); } const program = new Command(); program.name("repo-start").description("🚀 交互式项目模板选择和初始化工具").version(version); program.command("create").description("创建新项目").argument("[project-name]", "项目名称").action(async (projectName) => { console.log(chalk.blue.bold("\n🎯 欢迎使用 repo-start 项目初始化工具!\n")); try { if (!projectName) { const nameAnswer = await inquirer.prompt([ { type: "input", name: "projectName", message: "请输入项目名称:", validate: (input) => { if (!input.trim()) { return "项目名称不能为空"; } if (!/^[a-zA-Z0-9-_]+$/.test(input)) { return "项目名称只能包含字母、数字、连字符和下划线"; } return true; } } ]); projectName = nameAnswer.projectName; } const templateChoices = templates.map((template) => ({ name: `${chalk.green(template.name)} - ${chalk.dim(template.description)}`, value: template, short: template.name })); const { selectedTemplate } = await inquirer.prompt([ { type: "list", name: "selectedTemplate", message: "请选择一个项目模板:", choices: templateChoices } ]); const { confirm } = await inquirer.prompt([ { type: "confirm", name: "confirm", message: `确认要使用 "${selectedTemplate.name}" 模板创建项目 "${projectName}" 吗?`, default: true } ]); if (!confirm) { console.log(chalk.yellow("👋 操作已取消")); return; } const spinner = ora(`正在从 ${selectedTemplate.repository} 克隆模板...`).start(); try { const cloneCommand = `git clone ${selectedTemplate.repository} ${projectName}`; execSync(cloneCommand, { stdio: "pipe" }); spinner.succeed(chalk.green(`✅ 成功克隆模板到 ${projectName} 目录`)); if (selectedTemplate.installCommand) { const { shouldInstall } = await inquirer.prompt([ { type: "confirm", name: "shouldInstall", message: `是否要执行安装命令: ${selectedTemplate.installCommand}?`, default: true } ]); if (shouldInstall) { const installSpinner = ora("正在安装依赖...").start(); try { execSync(selectedTemplate.installCommand, { cwd: projectName, stdio: "pipe" }); installSpinner.succeed(chalk.green("✅ 依赖安装完成")); } catch (error) { installSpinner.fail(chalk.red("❌ 依赖安装失败")); console.log(chalk.yellow(`💡 你可以手动进入 ${projectName} 目录执行: ${selectedTemplate.installCommand}`)); } } } console.log(chalk.green.bold("\n🎉 项目创建成功!")); console.log(chalk.cyan("\n📝 下一步操作:")); console.log(chalk.white(` cd ${projectName}`)); if (selectedTemplate.startCommand) { console.log(chalk.white(` ${selectedTemplate.startCommand}`)); } if (selectedTemplate.tips) { console.log(chalk.yellow(` 💡 提示: ${selectedTemplate.tips}`)); } } catch (error) { spinner.fail(chalk.red("❌ 克隆模板失败")); console.error(chalk.red(`错误详情: ${error.message}`)); process.exit(1); } } catch (error) { console.error(chalk.red("❌ 发生错误:"), error.message); process.exit(1); } }); program.command("list").description("显示所有可用模板").action(() => { console.log(chalk.blue.bold("\n📋 可用模板列表:\n")); templates.forEach((template, index) => { console.log(chalk.green(`${index + 1}. ${template.name}`)); console.log(chalk.dim(` 描述: ${template.description}`)); console.log(chalk.dim(` 仓库: ${template.repository}`)); if (template.tags && template.tags.length > 0) { console.log(chalk.dim(` 标签: ${template.tags.join(", ")}`)); } console.log(); }); }); if (process.argv.length === 2) { program.help(); } program.parse(); //# sourceMappingURL=index.js.map