@tarojs/cli
Version:
cli tool for taro
434 lines • 18.2 kB
JavaScript
"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