UNPKG

@tarojs/cli

Version:
434 lines 18.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const path = require("node:path"); const binding_1 = require("@tarojs/binding"); const helper_1 = require("@tarojs/helper"); const shared_1 = require("@tarojs/shared"); const axios_1 = require("axios"); const inquirer = require("inquirer"); const ora = require("ora"); const semver = require("semver"); const util_1 = require("../util"); const constants_1 = require("./constants"); const creator_1 = require("./creator"); const fetchTemplate_1 = require("./fetchTemplate"); const NONE_AVAILABLE_TEMPLATE = '无可用模板'; class Project extends creator_1.default { constructor(options) { super(options.sourceRoot); this.askProjectName = function (conf, prompts) { if ((typeof conf.projectName) !== 'string') { prompts.push({ type: 'input', name: 'projectName', message: '请输入项目名称!', validate(input) { if (!input) { return '项目名不能为空!'; } if (helper_1.fs.existsSync(input)) { return '当前目录已经存在同名项目,请换一个项目名!'; } return true; } }); } else if (helper_1.fs.existsSync(conf.projectName)) { prompts.push({ type: 'input', name: 'projectName', message: '当前目录已经存在同名项目,请换一个项目名!', validate(input) { if (!input) { return '项目名不能为空!'; } if (helper_1.fs.existsSync(input)) { return '项目名依然重复!'; } return true; } }); } }; this.askDescription = function (conf, prompts) { if (typeof conf.description !== 'string') { prompts.push({ type: 'input', name: 'description', message: '请输入项目介绍' }); } }; this.askTypescript = function (conf, prompts) { if (typeof conf.typescript !== 'boolean') { prompts.push({ type: 'confirm', name: 'typescript', message: '是否需要使用 TypeScript ?' }); } }; this.askCSS = function (conf, prompts) { const cssChoices = [ { name: 'Sass', value: "Sass" /* CSSType.Sass */ }, { name: 'Less', value: "Less" /* CSSType.Less */ }, { name: 'Stylus', value: "Stylus" /* CSSType.Stylus */ }, { name: '无', value: "None" /* CSSType.None */ } ]; if (typeof conf.css !== 'string') { prompts.push({ type: 'list', name: 'css', message: '请选择 CSS 预处理器(Sass/Less/Stylus)', choices: cssChoices }); } }; this.askCompiler = function (conf, prompts) { const compilerChoices = [ { name: 'Webpack5', value: "Webpack5" /* CompilerType.Webpack5 */ }, { name: 'Vite', value: "Vite" /* CompilerType.Vite */ } ]; if (typeof conf.compiler !== 'string') { prompts.push({ type: 'list', name: 'compiler', message: '请选择编译工具', choices: compilerChoices }); } }; this.askFramework = function (conf, prompts) { const frameworks = [ { name: 'React', value: "React" /* FrameworkType.React */ }, { name: 'PReact', value: "Preact" /* FrameworkType.Preact */ }, { name: 'Vue3', value: "Vue3" /* FrameworkType.Vue3 */ }, { name: 'Solid', value: "Solid" /* FrameworkType.Solid */ } ]; if (typeof conf.framework !== 'string') { prompts.push({ type: 'list', name: 'framework', message: '请选择框架', choices: frameworks }); } }; this.askTemplateSource = function (conf, prompts) { return __awaiter(this, void 0, void 0, function* () { if (conf.template === 'default' || conf.templateSource) return; const homedir = (0, helper_1.getUserHomeDir)(); const taroConfigPath = path.join(homedir, helper_1.TARO_CONFIG_FOLDER); const taroConfig = path.join(taroConfigPath, helper_1.TARO_BASE_CONFIG); let localTemplateSource; // 检查本地配置 if (helper_1.fs.existsSync(taroConfig)) { // 存在则把模板源读出来 const config = yield helper_1.fs.readJSON(taroConfig); localTemplateSource = config === null || config === void 0 ? void 0 : config.templateSource; } else { // 不存在则创建配置 yield helper_1.fs.createFile(taroConfig); yield helper_1.fs.writeJSON(taroConfig, { templateSource: helper_1.DEFAULT_TEMPLATE_SRC }); localTemplateSource = helper_1.DEFAULT_TEMPLATE_SRC; } const choices = [ { name: 'Gitee(最快)', value: helper_1.DEFAULT_TEMPLATE_SRC_GITEE }, { name: 'Github(最新)', value: helper_1.DEFAULT_TEMPLATE_SRC }, { name: 'CLI 内置默认模板', value: 'default-template' }, { name: '自定义', value: 'self-input' }, { name: '社区优质模板源', value: 'open-source' } ]; if (localTemplateSource && localTemplateSource !== helper_1.DEFAULT_TEMPLATE_SRC && localTemplateSource !== helper_1.DEFAULT_TEMPLATE_SRC_GITEE) { choices.unshift({ name: `本地模板源:${localTemplateSource}`, value: localTemplateSource }); } prompts.push({ type: 'list', name: 'templateSource', message: '请选择模板源', choices }, { type: 'input', name: 'templateSource', message: '请输入模板源!', askAnswered: true, when(answers) { return answers.templateSource === 'self-input'; } }, { type: 'list', name: 'templateSource', message: '请选择社区模板源', choices(answers) { return __awaiter(this, void 0, void 0, function* () { const choices = yield getOpenSourceTemplates(answers.framework); return choices; }); }, askAnswered: true, when(answers) { return answers.templateSource === 'open-source'; } }); }); }; this.askTemplate = function (conf, prompts, list = []) { const choices = list.map(item => ({ name: item.desc ? `${item.name}(${item.desc})` : item.name, value: item.value || item.name })); if (!conf.hideDefaultTemplate) { choices.unshift({ name: '默认模板', value: 'default' }); } if (typeof conf.template !== 'string') { prompts.push({ type: 'list', name: 'template', message: '请选择模板', choices }); } }; this.askNpm = function (conf, prompts) { const packages = [ { name: 'yarn', value: "Yarn" /* NpmType.Yarn */ }, { name: 'pnpm', value: "Pnpm" /* NpmType.Pnpm */ }, { name: 'npm', value: "Npm" /* NpmType.Npm */ }, { name: 'cnpm', value: "Cnpm" /* NpmType.Cnpm */ } ]; if (typeof conf.npm !== 'string') { prompts.push({ type: 'list', name: 'npm', message: '请选择包管理工具', choices: packages }); } }; const unSupportedVer = semver.lt(process.version, 'v18.0.0'); if (unSupportedVer) { throw new Error('Node.js 版本过低,推荐升级 Node.js 至 v18.0.0+'); } this.rootPath = this._rootPath; this.conf = Object.assign({ projectName: '', projectDir: '', template: '', description: '', npm: '' }, options); } init() { (0, util_1.clearConsole)(); console.log(helper_1.chalk.green('Taro 即将创建一个新项目!')); console.log(`Need help? Go and open issue: ${helper_1.chalk.blueBright('https://tls.jd.com/taro-issue-helper')}`); console.log(); } create() { return __awaiter(this, void 0, void 0, function* () { try { const answers = yield this.ask(); const date = new Date(); this.conf = Object.assign(this.conf, answers); this.conf.date = `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`; this.write(); } catch (error) { console.log(helper_1.chalk.red('创建项目失败: ', error)); } }); } ask() { return __awaiter(this, void 0, void 0, function* () { let prompts = []; const conf = this.conf; this.askProjectName(conf, prompts); this.askDescription(conf, prompts); this.askFramework(conf, prompts); this.askTypescript(conf, prompts); this.askCSS(conf, prompts); this.askNpm(conf, prompts); const answers = yield inquirer.prompt(prompts); // Note: 由于 Solid 框架适配 Vite 还存在某些问题,所以在选择 Solid 框架时,不再询问编译工具 prompts = []; if (answers.framework === "Solid" /* FrameworkType.Solid */ || conf.framework === "Solid" /* FrameworkType.Solid */) { answers.compiler = "Webpack5" /* CompilerType.Webpack5 */; } else { this.askCompiler(conf, prompts); } yield this.askTemplateSource(conf, prompts); const compilerAndTemplateSourceAnswer = yield inquirer.prompt(prompts); prompts = []; const templates = yield this.fetchTemplates(Object.assign({}, answers, compilerAndTemplateSourceAnswer)); yield this.askTemplate(conf, prompts, templates); const templateChoiceAnswer = yield inquirer.prompt(prompts); return Object.assign(Object.assign(Object.assign({}, answers), compilerAndTemplateSourceAnswer), templateChoiceAnswer); }); } fetchTemplates(answers) { return __awaiter(this, void 0, void 0, function* () { const { templateSource, framework, compiler } = answers; this.conf.framework = this.conf.framework || framework || ''; this.conf.templateSource = this.conf.templateSource || templateSource; // 使用默认模版 if (answers.templateSource === 'default-template') { this.conf.template = 'default'; answers.templateSource = helper_1.DEFAULT_TEMPLATE_SRC_GITEE; } if (this.conf.template === 'default' || answers.templateSource === NONE_AVAILABLE_TEMPLATE) return Promise.resolve([]); // 从模板源下载模板 const isClone = /gitee/.test(this.conf.templateSource) || this.conf.clone; const templateChoices = yield (0, fetchTemplate_1.default)(this.conf.templateSource, this.templatePath(''), isClone); const filterFramework = (_framework) => { var _a; const current = (_a = this.conf.framework) === null || _a === void 0 ? void 0 : _a.toLowerCase(); if (typeof _framework === 'string' && _framework) { return current === _framework.toLowerCase(); } else if ((0, shared_1.isArray)(_framework)) { return _framework === null || _framework === void 0 ? void 0 : _framework.map(name => name.toLowerCase()).includes(current); } else { return true; } }; const filterCompiler = (_compiler) => { if (_compiler && (0, shared_1.isArray)(_compiler)) { return _compiler === null || _compiler === void 0 ? void 0 : _compiler.includes(compiler); } return true; }; // 根据用户选择的框架筛选模板 const newTemplateChoices = templateChoices .filter(templateChoice => { const { platforms, compiler } = templateChoice; return filterFramework(platforms) && filterCompiler(compiler); }); return newTemplateChoices; }); } write(cb) { this.conf.src = helper_1.SOURCE_DIR; const { projectName, projectDir, template, autoInstall = true, framework, npm } = this.conf; // 引入模板编写者的自定义逻辑 const templatePath = this.templatePath(template); const handlerPath = path.join(templatePath, constants_1.TEMPLATE_CREATOR); const handler = helper_1.fs.existsSync(handlerPath) ? require(handlerPath).handler : {}; (0, binding_1.createProject)({ projectRoot: projectDir, projectName, template, npm, framework, css: this.conf.css || "None" /* CSSType.None */, autoInstall: autoInstall, templateRoot: (0, util_1.getRootPath)(), version: (0, util_1.getPkgVersion)(), typescript: this.conf.typescript, date: this.conf.date, description: this.conf.description, compiler: this.conf.compiler, period: "CreateAPP" /* PeriodType.CreateAPP */, }, handler).then(() => { cb && cb(); }); } } exports.default = Project; function getOpenSourceTemplates(platform) { return new Promise((resolve, reject) => { const spinner = ora({ text: '正在拉取开源模板列表...', discardStdin: false }).start(); axios_1.default.get('https://gitee.com/NervJS/awesome-taro/raw/next/index.json') .then(response => { spinner.succeed(`${helper_1.chalk.grey('拉取开源模板列表成功!')}`); const collection = response.data; switch (platform.toLowerCase()) { case 'react': return resolve(collection.react); default: return resolve([NONE_AVAILABLE_TEMPLATE]); } }) .catch(_error => { spinner.fail(helper_1.chalk.red('拉取开源模板列表失败!')); return reject(new Error()); }); }); } //# sourceMappingURL=project.js.map