UNPKG

@opentiny/tiny-toolkit-pro

Version:

TinyPro Vue:开箱即用、前后端分离的 Vue 后台管理模板

435 lines 34.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.installDependencies = void 0; const yaml_1 = require("yaml"); const path = __importStar(require("path")); const dotenv = __importStar(require("dotenv")); const fs_extra_1 = require("fs-extra"); const chalk_1 = __importDefault(require("chalk")); const cross_spawn_1 = __importDefault(require("cross-spawn")); const inquirer_1 = __importDefault(require("inquirer")); const cli_devkit_1 = require("@opentiny/cli-devkit"); const interfaces_1 = require("./interfaces"); const utils_1 = __importDefault(require("./utils")); const fs_1 = require("fs"); const log = (0, cli_devkit_1.logs)('tiny-toolkit-pro'); const VUE_TEMPLATE_PATH = 'tinyvue'; const DEFAULT_PROJECT_NAME = 'tiny-pro'; /** * 询问创建项目的描述,使用的技术栈 * * @returns object { description: 项目描述,framework: 框架, name: 项目名称 ,serverFramework:使用技术栈, dialect:数据库,DB_host:数据库地址,DB_port:数据库端口,database:数据库名称,username:数据库用户名,password:数据库密码,} */ const getProjectInfo = () => { const question = [ { type: 'input', name: 'name', message: '请输入项目名称:', default: DEFAULT_PROJECT_NAME, // 必填校验 validate: (input) => Boolean(input), }, { type: 'input', name: 'description', message: '请输入项目描述:', default: '基于TinyPro套件创建的中后台系统', }, { type: 'list', name: 'framework', message: '请选择您希望使用的客户端技术栈:', choices: [{ name: 'vue', value: VUE_TEMPLATE_PATH }], default: VUE_TEMPLATE_PATH, prefix: '*', }, { type: 'list', name: 'serverFramework', message: '请选择您希望使用的服务端技术栈:', choices: [ // { name: 'Egg.js', value: ServerFrameworks.EggJs }, // { name: 'Spring Cloud', value: ServerFrameworks.SpringCloud }, { name: 'Nest.js', value: interfaces_1.ServerFrameworks.NestJs }, { name: '暂不配置', value: interfaces_1.ServerFrameworks.Skip }, ], default: interfaces_1.ServerFrameworks.NestJs, prefix: '*', when: (answers) => answers.framework === VUE_TEMPLATE_PATH, }, { type: 'list', name: 'buildTool', message: '请选择你想要的构建工具: ', choices: [ { name: 'Vite', value: interfaces_1.BuildTool.Vite }, { name: 'Webpack', value: interfaces_1.BuildTool.Webpack }, { name: 'Rspack', value: interfaces_1.BuildTool.Rspack }, { name: 'Farm', value: interfaces_1.BuildTool.Farm }, ], default: interfaces_1.BuildTool.Vite, prefix: '*', }, { type: 'list', name: 'serverConfirm', message: '请确保已安装数据库服务(参考文档 https://www.opentiny.design/tiny-cli/docs/toolkits/pro#database):', choices: [ { name: '已完成数据库服务安装,开始配置', value: true }, { name: '暂不配置服务端', value: false }, ], prefix: '*', when: (answers) => answers.framework === VUE_TEMPLATE_PATH && answers.serverFramework !== interfaces_1.ServerFrameworks.Skip, }, { type: 'input', name: 'redisHost', message: '请输入Redis地址:', default: 'localhost', prefix: '*', when: (answers) => answers.serverConfirm, }, { type: 'input', name: 'redisPort', message: '请输入Redis端口:', default: 6379, prefix: '*', when: (answers) => answers.serverConfirm, }, { type: 'list', name: 'dialect', message: '请选择数据库类型:', choices: [ { name: 'MySql', value: 'mysql' }, { name: '暂不配置', value: '' }, ], default: 'mysql', prefix: '*', when: (answers) => answers.serverConfirm, }, { type: 'input', name: 'host', message: '请输入数据库地址:', default: 'localhost', prefix: '*', when: (answers) => answers.dialect, }, { type: 'input', name: 'port', message: '请输入数据库端口:', default: 3306, prefix: '*', when: (answers) => answers.host, }, { type: 'input', name: 'database', message: '请输入数据库名称:', prefix: '*', validate: (input) => Boolean(input), when: (answers) => answers.host, }, { type: 'input', name: 'username', message: '请输入登录用户名:', default: 'root', prefix: '*', when: (answers) => answers.host, }, { type: 'password', name: 'password', message: '请输入密码:', prefix: '*', when: (answers) => answers.host, }, ]; return inquirer_1.default.prompt(question); }; /** * 同步创建服务端项目文件目录、文件 * @answers 询问客户端问题的选择值 * @dbAnswers 询问服务端配置的选择值 */ const createServerSync = (answers) => { var _a, _b, _c, _d, _e, _f; const { name, serverFramework } = answers; // 复制服务端相关目录 const serverFrom = utils_1.default.getTemplatePath(`${serverFramework}`); const serverTo = utils_1.default.getDistPath(`${name}/${serverFramework}`); const config = { DATABASE_HOST: answers.dialect && ((_a = answers.host) !== null && _a !== void 0 ? _a : 'localhost'), DATABASE_PORT: answers.dialect && Number((_b = answers.port) !== null && _b !== void 0 ? _b : 3306), DATABASE_USERNAME: answers.dialect && ((_c = answers.username) !== null && _c !== void 0 ? _c : 'root'), DATABASE_PASSWORD: answers.dialect && ((_d = answers.password) !== null && _d !== void 0 ? _d : 'root'), DATABASE_NAME: answers.dialect && answers.database, DATABASE_SYNCHRONIZE: false, DATABASE_AUTOLOADENTITIES: true, AUTH_SECRET: 'secret', REDIS_SECONDS: 7200, REDIS_HOST: (_e = answers.redisHost) !== null && _e !== void 0 ? _e : 'localhost', REDIS_PORT: Number((_f = answers.redisPort) !== null && _f !== void 0 ? _f : 6379), EXPIRES_IN: '2h', PAGINATION_PAGE: 1, PAGINATION_LIMIT: 10, }; const envStr = objToEnv(config); const overwriteDockerComposeConfig = { // @see https://hub.docker.com/_/mysql // This variable is mandatory and specifies the password that will be set for the MySQL root superuser account. MYSQL_ROOT_PASSWORD: config.DATABASE_PASSWORD, MYSQL_DATABASE: config.DATABASE_NAME, MYSQL_USER: config.DATABASE_USERNAME === 'root' ? undefined : config.DATABASE_NAME, MYSQL_PASSWORD: config.DATABASE_USERNAME === 'root' ? undefined : config.DATABASE_PASSWORD, }; (0, fs_extra_1.copySync)(serverFrom, serverTo); (0, fs_1.writeFileSync)(path.join(serverTo, '.env'), envStr); const dockerComposeYaml = (0, fs_1.readFileSync)(path.join(serverTo, 'docker-compose.yml')).toString(); const yaml = (0, yaml_1.parse)(dockerComposeYaml); const { services } = yaml; const mysql = services.mysql; mysql.environment = overwriteDockerComposeConfig; (0, fs_1.writeFileSync)(path.join(serverTo, 'docker-compose.yml'), (0, yaml_1.stringify)(yaml)); }; // eslint-disable-next-line @typescript-eslint/no-explicit-any const objToEnv = (obj) => { return Object.entries(obj) .map(([key, value]) => { const v = typeof value === 'string' ? `'${value}'` : value; return [key, '=', v].join(' '); }) .join('\n'); }; const packageJsonProcess = (buildTool, packages, currentPath) => { const match = (pattern, items) => { return items.filter((item) => pattern.test(item)); }; const removeDeps = () => { const devDeps = interfaces_1.devDependencies[buildTool]; devDeps.forEach((devDep) => { if (typeof devDep === 'string') { packages.devDependencies[devDep] = undefined; } if (devDep instanceof RegExp) { const deps = match(devDep, Object.keys(packages.devDependencies)); if (!deps.length) { return; } deps.forEach((dep) => { if (packages.devDependencies[dep]) { packages.devDependencies[dep] = undefined; } }); } }); const dependencies = interfaces_1.removeDependencies[buildTool]; dependencies.forEach((dep) => { if (typeof dep === 'string') { if (!packages.dependencies[dep]) { return; } packages.dependencies[dep] = undefined; } if (dep instanceof RegExp) { const keys = match(dep, Object.keys(packages.devDependencies)); keys.forEach((key) => { if (!packages.dependencies[key]) { return; } packages.dependencies[key] = undefined; }); } }); }; const replaceScript = (name, command) => { packages.scripts[name] = command; }; const removeScripts = () => { const scripts = interfaces_1.removedCommand; scripts.forEach((script) => { replaceScript(script, undefined); }); }; const replaceBuildCommand = () => { const command = interfaces_1.buildCommand[buildTool]; replaceScript('build', command); }; const replaceDevCommand = () => { const command = interfaces_1.devCommand[buildTool]; replaceScript('start', command); }; const remove = () => { const removedPaths = interfaces_1.buildConfigs[buildTool]; const paths = removedPaths .filter((removedPath) => (0, fs_1.existsSync)(path.join(currentPath, removedPath))) .map((p) => path.join(currentPath, p)); if (!paths.length) { return; } let willRemovePath = ''; try { paths.forEach((removePath) => { willRemovePath = removePath; (0, fs_1.rmSync)(removePath, { recursive: true, force: true }); }); } catch (_a) { log.error(`删除${willRemovePath}错误`); } }; removeDeps(); removeScripts(); replaceBuildCommand(); replaceDevCommand(); return remove; }; /** * 同步创建客户端项目文件目录、文件 * @answers 询问客户端问题的选择值 * @dbAnswers 询问服务端配置的选择值 */ const createProjectSync = (answers) => { const { description, name, serverConfirm, buildTool } = answers; const templatePath = interfaces_1.VueVersion.Vue3; // 模板来源目录 const from = utils_1.default.getTemplatePath(templatePath); // 复制模板的目标目录 const to = utils_1.default.getDistPath(serverConfirm ? `${name}/web` : name); cli_devkit_1.fs.copyTpl(from, to); // 将项目名称、描述写入 package.json中 try { const packageJsonPath = path.join(to, 'package.json'); let packageJson = JSON.parse(cli_devkit_1.fs.readFileSync(packageJsonPath, { encoding: 'utf8' })); packageJson = Object.assign(Object.assign({}, packageJson), { name, description }); const remove = packageJsonProcess(buildTool, packageJson, to); cli_devkit_1.fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), { encoding: 'utf8', }); remove(); } catch (e) { log.error(e); log.error('配置项目信息创建失败'); } // 如果不对接服务端,全部接口采用mock if (!serverConfirm) { try { const envPath = path.join(to, '.env'); const envConfig = dotenv.parse(cli_devkit_1.fs.readFileSync(envPath, { encoding: 'utf8' })); delete envConfig.VITE_MOCK_IGNORE; const config = Object.keys(envConfig) .map((key) => `${key} = ${envConfig[key]}`) .join('\n'); cli_devkit_1.fs.writeFileSync(envPath, config); } catch (e) { log.error(e); log.error('开启mock模式失败'); log.info('请手动配置env信息'); } } else { // 如果对接服务端,执行文件复制及相关配置( WIP: 后台接口暂未全量完成,部分接口还是使用mock ) createServerSync(answers); } }; // 安装依赖 const installDependencies = (answers) => { const prefix = cli_devkit_1.cliConfig.getBinName(); const { name, serverFramework, serverConfirm } = answers; // egg服务端 安装依赖并启动 if (serverConfirm && serverFramework === interfaces_1.ServerFrameworks.EggJs) { log.info('正在安装服务端 npm 依赖,安装过程需要几十秒,请耐心等待...'); const installServiceResult = cross_spawn_1.default.sync('npm', ['install'], { cwd: `${name}/${serverFramework}/`, stdio: 'inherit', }); if (installServiceResult.status === 0) { log.success('服务端 npm 依赖安装成功'); } else { throw new Error(installServiceResult.error); } } // npm 依赖安装 log.info('正在安装客户端 npm 依赖,安装过程需要几十秒,请耐心等待...'); const installClientResult = cross_spawn_1.default.sync('npm', ['install'], { cwd: serverConfirm ? `${name}/web` : `${name}/`, stdio: 'inherit', }); if (installClientResult.status === 0) { log.success('客户端 npm 依赖安装成功'); } else { throw new Error(installClientResult.error); } /* prettier-ignore-start */ console.log(chalk_1.default.yellow('\n--------------------初始化成功,请按下面提示进行操作--------------------\n')); if (serverConfirm) { console.log(chalk_1.default.green(`${chalk_1.default.yellow(`$ cd ${name}/web && npm run start`)} # 开启web开发环境`)); console.log(chalk_1.default.green(`${chalk_1.default.yellow(serverFramework === interfaces_1.ServerFrameworks.SpringCloud ? `请查看 ${name}/${serverFramework}/README_CN.md ` : `$ cd ${name}/${serverFramework} && npm run dev`)} # 开启server开发环境`)); } else { console.log(chalk_1.default.green(`${chalk_1.default.yellow(`$ cd ${name} && ${prefix} start`)} # 可一键开启项目开发环境`)); } console.log(chalk_1.default.green(`${chalk_1.default.yellow(`$ ${prefix} help`)} # 可查看当前套件的详细帮助`)); console.log(chalk_1.default.green(`\n建议将现有初始化的代码提交一次到master分支, 方便后续切换到 ${chalk_1.default.yellow('daily/x.y.z')} 分支进行开发`)); console.log(chalk_1.default.yellow('\n-------------------- 技术支持:官方小助手微信opentiny-official --------------------\n')); }; exports.installDependencies = installDependencies; exports.default = async () => { // 拷贝模板到当前目录 let projectInfo; try { // 创建项目文件夹及文件 projectInfo = await getProjectInfo(); createProjectSync(projectInfo); } catch (e) { log.error(e); log.error('项目模板创建失败'); return; } // 初始化数据库 // 初始化不应该在cli做,而是在后端 // 安装依赖 log.info('初始化成功,请运行npm i或tiny i 安装依赖'); }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvaW5pdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtCQUF3QztBQUN4QywyQ0FBNkI7QUFDN0IsK0NBQWlDO0FBQ2pDLHVDQUFvQztBQUNwQyxrREFBMEI7QUFDMUIsOERBQWdDO0FBQ2hDLHdEQUF3RDtBQUN4RCxxREFBMkQ7QUFDM0QsNkNBV3NCO0FBQ3RCLG9EQUE0QjtBQUM1QiwyQkFBcUU7QUFFckUsTUFBTSxHQUFHLEdBQUcsSUFBQSxpQkFBSSxFQUFDLGtCQUFrQixDQUFDLENBQUM7QUFDckMsTUFBTSxpQkFBaUIsR0FBRyxTQUFTLENBQUM7QUFDcEMsTUFBTSxvQkFBb0IsR0FBRyxVQUFVLENBQUM7QUFFeEM7Ozs7R0FJRztBQUNILE1BQU0sY0FBYyxHQUFHLEdBQXlCLEVBQUU7SUFDaEQsTUFBTSxRQUFRLEdBQW9DO1FBQ2hEO1lBQ0UsSUFBSSxFQUFFLE9BQU87WUFDYixJQUFJLEVBQUUsTUFBTTtZQUNaLE9BQU8sRUFBRSxVQUFVO1lBQ25CLE9BQU8sRUFBRSxvQkFBb0I7WUFDN0IsT0FBTztZQUNQLFFBQVEsRUFBRSxDQUFDLEtBQWEsRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztTQUM1QztRQUNEO1lBQ0UsSUFBSSxFQUFFLE9BQU87WUFDYixJQUFJLEVBQUUsYUFBYTtZQUNuQixPQUFPLEVBQUUsVUFBVTtZQUNuQixPQUFPLEVBQUUscUJBQXFCO1NBQy9CO1FBQ0Q7WUFDRSxJQUFJLEVBQUUsTUFBTTtZQUNaLElBQUksRUFBRSxXQUFXO1lBQ2pCLE9BQU8sRUFBRSxrQkFBa0I7WUFDM0IsT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxDQUFDO1lBQ3BELE9BQU8sRUFBRSxpQkFBaUI7WUFDMUIsTUFBTSxF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