UNPKG

create-arena-project

Version:

神奇代码岛<->VSCode,从这里开始,创建一个神岛代码项目的脚手架。

228 lines (205 loc) 7.84 kB
#!/usr/bin/env node /** * @fileoverview 神岛代码项目创建工具的入口文件 * 该文件负责处理用户交互,收集项目配置信息,并调用相关模块完成项目初始化 */ import { default as chalk } from "chalk"; import { resolve, isAbsolute } from "path"; import yargs from "yargs"; import { hideBin } from "yargs/helpers"; import { install } from "./install.js"; import skeleton from "./skeleton.js"; import { ConfigWizard } from "./config-wizard.js"; import { errorHandler, ErrorType } from "./error-handler.js"; // 设置错误处理器 errorHandler.debug = process.env.DEBUG === "true"; /** * 项目创建的核心逻辑 * @param {string} basepath - 项目基础路径 * @param {object} answers - 配置答案 * @param {object} selectedTemplate - 选定的模板 */ async function createProject(basepath, answers, selectedTemplate = null) { try { // 显示项目创建进度 console.log(chalk.cyan("\n🚀 项目创建进度:")); console.log(chalk.dim("----------------------------------------")); // 步骤1:创建项目骨架 console.log(chalk.cyan("[1/3] 🏗️ 创建项目骨架")); console.log(chalk.dim("• 生成目录结构")); console.log(chalk.dim("• 配置基础文件")); console.log(chalk.dim("• 设置开发环境")); // 记录状态,但不创建日志文件 console.log(chalk.blue("[信息] [项目创建] 开始创建项目骨架")); // 如果选择了项目模板,将模板信息添加到配置中 if (selectedTemplate) { answers.template = { value: selectedTemplate.id }; } await skeleton.skeleton( isAbsolute(basepath) ? basepath : resolve(process.cwd(), basepath), answers ); console.log(chalk.green("✓ 项目骨架创建完成")); console.log(chalk.blue("[信息] [项目创建] 项目骨架创建完成")); // 步骤2:安装依赖 console.log(chalk.cyan("\n[2/3] 📦 安装项目依赖")); console.log(chalk.dim("• 安装核心依赖")); console.log(chalk.dim("• 安装开发工具")); console.log(chalk.dim("• 配置构建脚本")); // 记录状态 console.log(chalk.blue("[信息] [依赖安装] 开始安装项目依赖")); await install(basepath, answers); console.log(chalk.green("✓ 依赖安装完成")); // 步骤3:完成配置 console.log(chalk.cyan("\n[3/3] ⚙️ 完成项目配置")); console.log(chalk.dim("• 更新配置文件")); console.log(chalk.dim("• 设置开发环境")); console.log(chalk.dim("• 初始化版本控制")); console.log(chalk.green("✓ 配置完成")); console.log(chalk.dim("----------------------------------------")); console.log(chalk.blue("[信息] [项目创建] 项目创建完成")); } catch (error) { await errorHandler.handleError( error, ErrorType.UNKNOWN, "项目创建过程", () => { console.error(chalk.redBright("项目创建过程中发生错误:"), error); } ); process.exit(1); } // 显示项目创建成功的信息 const path = resolve(process.cwd(), basepath); // 显示项目配置信息 console.log(chalk.yellowBright("\n📋 ArenaPro项目配置信息")); console.log(chalk.dim("----------------------------------------")); console.log(chalk.cyan("📁 项目目录:") + " " + path); console.log(chalk.cyan("🔧 基础配置:")); console.log(` • 开发语言: ${answers.languageType.value}`); console.log(` • 代码规范: ${answers.prettier.value}`); console.log(` • 国际化: ${answers.i18n.value}`); console.log( ` • 项目类型:${answers.npmPackage.value}${ answers.isServer.value ? ` (${answers.isServer.value})` : "" }` ); if (selectedTemplate) { console.log(chalk.cyan("\n📋 项目模板:")); console.log(` • 模板名称:${selectedTemplate.name}`); console.log(` • 模板特性:${selectedTemplate.features.join(", ")}`); } const entryExt = answers.languageType.value === "TypeScript" ? ".ts" : ".js"; console.log(chalk.cyan("\n⚙️ 共享代码:")); console.log(` • ${path}/shares/sharesApp${entryExt}`); if (!answers.isServer.value || answers.isServer.value === "服务端") { console.log(chalk.cyan("\n⚙️ 服务端:")); console.log(` • ${path}/server/src/App${entryExt}`); } if (!answers.isServer.value || answers.isServer.value === "客户端") { console.log(chalk.cyan("\n⚙️ 客户端:")); console.log(` • ${path}/client/src/clientApp${entryExt}`); } console.log(chalk.cyan("\n⚙️ 配置文件:")); console.log(` • ${path}/dao3.config.json`); console.log(chalk.dim("----------------------------------------")); console.log(chalk.green("\n✨ 恭喜!项目创建成功!")); } /** * 主函数,用于引导用户进行项目创建的配置选择 * 包含项目类型、编程语言、代码规范等配置项的交互式选择 */ (async function main() { const argv = yargs(hideBin(process.argv)) .option("name", { alias: "n", type: "string", description: "项目名称", coerce: (arg) => { if (arg && !/^[a-zA-Z0-9_./-]+$/.test(arg)) { throw new Error( "项目路径只能包含英文字母、数字、下划线、连字符、点 (.) 和斜杠 (/)" ); } return arg; }, }) .option("type", { alias: "t", type: "string", description: "项目类型 (map 或 npm)", default: "map", }) .option("lang", { alias: "l", type: "string", description: "开发语言 (ts 或 js)", default: "ts", }) .option("prettier", { type: "boolean", description: "配置代码规范工具", default: false, }) .option("i18n", { type: "boolean", description: "配置国际化", default: false, }) .option("side", { type: "string", description: "项目包含的端 (both, server 或 client)", default: "both", }) .option("dependentManner", { type: "string", description: "项目依赖方式 (npm 或 yarn 或 pnpm 或 bun)", default: "npm", }) .help() .alias("help", "h").argv; try { if (argv.name) { // 非交互式模式 const answers = { npmPackage: { value: argv.type === "npm" ? "神岛组件库" : "神岛地图项目", }, languageType: { value: argv.lang === "js" ? "JavaScript" : "TypeScript", }, prettier: { value: argv.prettier ? "配置" : "跳过" }, i18n: { value: argv.i18n ? "配置" : "跳过" }, isServer: { value: argv.type === "map" ? { server: "仅服务端", client: "仅客户端", both: "服务端和客户端", }[argv.side] || "服务端和客户端" : "", }, dependentManner: { value: argv.dependentManner, }, }; const basepath = argv.name; await createProject(basepath, answers); } else { const configWizard = new ConfigWizard({ showTemplates: false, showAdvancedOptions: false, }); const { answers, basepath, selectedTemplate } = await configWizard.run(); await createProject(basepath, answers, selectedTemplate); } } catch (error) { await errorHandler.handleError(error, ErrorType.UNKNOWN, "项目创建", () => { console.log(chalk.red("\n❌ 创建项目失败")); console.log(chalk.dim("----------------------------------------")); console.error(chalk.red(`错误详情: ${error.message}`)); }); process.exit(1); } })();