UNPKG

@gaonengwww/tiny-toolkit-pro

Version:

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

507 lines 43.6 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 properties_parser_1 = require("properties-parser"); 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: 'SpringBoot', value: interfaces_1.ServerFrameworks.SpringBoot }, { 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, _g, _h, _j, _k, _l, _m, _o; const { name, serverFramework } = answers; // 复制服务端相关目录 const serverFrom = utils_1.default.getTemplatePath(`${serverFramework}`); const serverTo = utils_1.default.getDistPath(`${name}/${serverFramework}`); if (serverFramework == interfaces_1.ServerFrameworks.SpringBoot) { console.log('springboot的服务端配置'); // 拷贝 SpringBoot 模板代码到目标目录 (0, fs_extra_1.copySync)(serverFrom, serverTo); // ===== 1. 定义统一的配置对象(从用户输入中提取,不写死)===== const config = { DB_HOST: (_a = answers.host) !== null && _a !== void 0 ? _a : 'localhost', DB_PORT: Number((_b = answers.port) !== null && _b !== void 0 ? _b : 3306), DB_USERNAME: (_c = answers.username) !== null && _c !== void 0 ? _c : 'root', DB_PASSWORD: (_d = answers.password) !== null && _d !== void 0 ? _d : 'root', DB_NAME: (_e = answers.database) !== null && _e !== void 0 ? _e : 'mydb', DB_SYNCHRONIZE: false, DB_AUTOLOADENTITIES: true, AUTH_SECRET: 'secret', REDIS_SECONDS: 7200, REDIS_HOST: (_f = answers.redisHost) !== null && _f !== void 0 ? _f : 'localhost', REDIS_PORT: Number((_g = answers.redisPort) !== null && _g !== void 0 ? _g : 6379), EXPIRES_IN: '2h', PAGINATION_PAGE: 1, PAGINATION_LIMIT: 10, SERVER_PORT: 3000, // 可以改为 answers.serverPort || 3000,如果将来要支持动态端口 }; // ===== 2. 拷贝模板后,设置 Spring Boot 配置文件路径 ===== const propertiesFilePath = path.join(serverTo, 'src/main/resources/application.properties'); if (!(0, fs_1.existsSync)(propertiesFilePath)) { log.error(`❌ 未找到 Spring Boot 配置文件:${propertiesFilePath}`); return; } if (!(0, fs_1.existsSync)(propertiesFilePath)) { log.error(`❌ 未找到 Spring Boot 配置文件:${propertiesFilePath}`); return; } // ✅ 1. 使用 createEditor 读取 properties 文件 const editor = (0, properties_parser_1.createEditor)(propertiesFilePath); // ✅ 3. 使用 editor.set(...) 方法逐一设置每一个配置项 editor.set('server.port', config.SERVER_PORT.toString()); // 动态端口 editor.set('spring.datasource.url', `jdbc:mysql://${config.DB_HOST}:${config.DB_PORT}/${config.DB_NAME}?allowMultiQueries=true&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&allowPublicKeyRetrieval=true&useSSL=false`); editor.set('spring.datasource.username', config.DB_USERNAME); editor.set('spring.datasource.password', config.DB_PASSWORD); editor.set('spring.datasource.driver-class-name', 'com.mysql.cj.jdbc.Driver'); // HikariCP 配置 editor.set('spring.datasource.hikari.pool-name', 'HikariCPDatasource'); editor.set('spring.datasource.hikari.minimum-idle', '5'); editor.set('spring.datasource.hikari.idle-timeout', '180000'); editor.set('spring.datasource.hikari.maximum-pool-size', '10'); editor.set('spring.datasource.hikari.auto-commit', 'true'); editor.set('spring.datasource.hikari.max-lifetime', '180000'); editor.set('spring.datasource.hikari.connection-timeout', '30000'); // MyBatis-Plus editor.set('mybatis-plus.mapper-locations', 'classpath:mappers/*.xml'); editor.set('mybatis-plus.type-aliases-package', 'com.TinyPro.entity.po'); editor.set('mybatis-plus.configuration.map-underscore-to-camel-case', 'true'); editor.set('mybatis-plus.configuration.default-enum-type-handler', 'org.apache.ibatis.type.EnumOrdinalTypeHandler'); // JPA (如同时使用) editor.set('spring.jpa.hibernate.ddl-auto', 'update'); editor.set('spring.jpa.database-platform', 'org.hibernate.dialect.MySQL8Dialect'); editor.set('spring.jpa.properties.hibernate.dialect', 'org.hibernate.dialect.MySQL8Dialect'); editor.set('spring.jpa.properties.hibernate.dialect.storage_engine', 'innodb'); editor.set('spring.jpa.properties.hibernate.globally_quoted_identifiers', 'true'); editor.set('spring.jpa.hibernate.naming.physical-strategy', 'org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl'); // JWT editor.set('jwt.secret', '0Zi4SA=='); // Redis editor.set('spring.data.redis.host', config.REDIS_HOST); editor.set('spring.data.redis.port', config.REDIS_PORT.toString()); // ✅ 4. 保存修改后的内容到原 .properties 文件 editor.save(propertiesFilePath); log.success(`✅ Spring Boot 配置文件已更新:${propertiesFilePath}`); } else if (serverFramework == interfaces_1.ServerFrameworks.NestJs) { const config = { DATABASE_HOST: answers.dialect && ((_h = answers.host) !== null && _h !== void 0 ? _h : 'localhost'), DATABASE_PORT: answers.dialect && Number((_j = answers.port) !== null && _j !== void 0 ? _j : 3306), DATABASE_USERNAME: answers.dialect && ((_k = answers.username) !== null && _k !== void 0 ? _k : 'root'), DATABASE_PASSWORD: answers.dialect && ((_l = answers.password) !== null && _l !== void 0 ? _l : 'root'), DATABASE_NAME: answers.dialect && answers.database, DATABASE_SYNCHRONIZE: false, DATABASE_AUTOLOADENTITIES: true, AUTH_SECRET: 'secret', REDIS_SECONDS: 7200, REDIS_HOST: (_m = answers.redisHost) !== null && _m !== void 0 ? _m : 'localhost', REDIS_PORT: Number((_o = answers.redisPort) !== null && _o !== void 0 ? _o : 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, serverFramework } = 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中 if (serverFramework == interfaces_1.ServerFrameworks.NestJs) { 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 { console.log('执行文件复制及相关配置( WIP: 后台接口暂未全量完成,部分接口还是使用mock )'); // 如果对接服务端,执行文件复制及相关配置( 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.SpringBoot ? `请查看 ${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; } log.info('初始化成功,请运行npm i或tiny i 安装依赖'); }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvaW5pdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLCtCQUF3QztBQUN4QywyQ0FBNkI7QUFDN0IsK0NBQWlDO0FBQ2pDLHVDQUFvQztBQUNwQyxrREFBMEI7QUFDMUIsOERBQWdDO0FBQ2hDLHdEQUF3RDtBQUN4RCxxREFBMkQ7QUFDM0QseURBQWlEO0FBQ2pELDZDQVdzQjtBQUN0QixvREFBNEI7QUFDNUIsMkJBQXFFO0FBRXJFLE1BQU0sR0FBRyxHQUFHLElBQUEsaUJBQUksRUFBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBQ3JDLE1BQU0saUJBQWlCLEdBQUcsU0FBUyxDQUFDO0FBQ3BDLE1BQU0sb0JBQW9CLEdBQUcsVUFBVSxDQUFDO0FBRXhDOzs7O0dBSUc7QUFDSCxNQUFNLGNBQWMsR0FBRyxHQUF5QixFQUFFO0lBQ2hELE1BQU0sUUFBUSxHQUFvQztRQUNoRDtZQUNFLElBQUksRUFBRSxPQUFPO1lBQ2IsSUFBSSxFQUFFLE1BQU07WUFDWixPQUFPLEVBQUUsVUFBVTtZQUNuQixPQUFPLEVBQUUsb0JBQW9CO1lBQzdCLE9BQU87WUFDUCxRQUFRLEVBQUUsQ0FBQyxLQUFhLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7U0FDNUM7UUFDRDtZQUNFLElBQUksRUFBRSxPQUFPO1lBQ2IsSUFBSSxFQUFFLGFBQWE7WUFDbkIsT0FBTyxFQUFFLFVBQVU7WUFDbkIsT0FBTyxFQUFFLHFCQUFxQjtTQUMvQjtRQUNEO1lBQ0UsSUFBSSxFQUFFLE1BQU07WUFDWixJQUFJLEVBQUUsV0FBVztZQUNqQixPQUFPLEVBQUUsa0JBQWtCO1lBQzNCLE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQztZQUNwRCxPQUFPLEVBQUUsaUJBQWlC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