#!/usr/bin/env node /** * 代码生成统一入口脚本 * 整合了model生成和api生成功能 */ const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const { generateApi } = require('./gen_api'); // 读取配置文件 const CONFIG_FILE = path.join(__dirname, 'config.json'); let config = {}; try { if (fs.existsSync(CONFIG_FILE)) { const configContent = fs.readFileSync(CONFIG_FILE, 'utf8'); config = JSON.parse(configContent); console.log('Configuration loaded from config.json'); } else { console.log('config.json not found, using default settings'); } } catch (error) { console.error('Error loading configuration:', error.message); console.log('Using default settings'); } // 默认数据库配置 const modelConfig = config.model || { // 数据库连接信息 dbUrl: 'qnc:5vg67b3UNHu8@tcp(127.0.0.1:21001)/qnc', // 输出目录 outputDir: './model', // 模板目录 templateDir: '../template', // 目标目录 targetDir: '../../app/user/model', // 表名列表 tables: [ 'agent', 'agent_audit', 'agent_real_name' ], // 禁用的表名列表 disabledTables: [] }; // 默认API配置 const apiConfig = config.api || { // API定义文件路径 apiFile: './app/user/cmd/api/desc/main.api', // 输出目录 outputDir: './app/user/cmd/api', // 模板目录 templateDir: './deploy/template', // 是否使用样式 useStyle: false }; /** * 将表名转换为驼峰命名法 * @param {string} tableName 表名 * @returns {string} 驼峰命名的表名 */ function convertToCamelCase(tableName) { try { // 将表名按_分割,并将每个部分首字母大写 const parts = tableName.split('_'); let camelCase = ''; for (const part of parts) { if (part.length > 0) { camelCase += part.charAt(0).toUpperCase() + part.slice(1).toLowerCase(); } } return camelCase; } catch (error) { console.error(`Error in convertToCamelCase for table: ${tableName}`); console.error(error.message); return tableName; // 出错时返回原表名 } } /** * 确保目录存在 * @param {string} dirPath 目录路径 */ function ensureDirectoryExists(dirPath) { if (!fs.existsSync(dirPath)) { console.log(`Creating directory: ${dirPath}`); fs.mkdirSync(dirPath, { recursive: true }); } } /** * 为单个表生成模型 * @param {string} table 表名 * @param {object} config 配置信息 */ function generateModelForTable(table, config) { try { console.log('========================================='); console.log(`Processing table: ${table}`); // 生成模型 console.log('Generating model...'); const command = `goctl model mysql datasource -url="${config.dbUrl}" -table="${table}" -dir="${config.outputDir}" --home="${config.templateDir}" -cache=true --style=goZero`; console.log(`Running command: ${command}`); execSync(command, { stdio: 'inherit' }); // 将表名转换为驼峰命名法 const camelCaseName = convertToCamelCase(table); console.log(`Table name converted to: ${camelCaseName}`); // 定义源文件和目标文件路径 const sourceModelFile = path.join(config.outputDir, `${camelCaseName}Model.go`); const sourceModelGenFile = path.join(config.outputDir, `${camelCaseName}Model_gen.go`); const targetModelFile = path.join(config.targetDir, `${camelCaseName}Model.go`); const targetModelGenFile = path.join(config.targetDir, `${camelCaseName}Model_gen.go`); console.log('Source files:'); console.log(` - ${sourceModelFile}`); console.log(` - ${sourceModelGenFile}`); console.log('Target files:'); console.log(` - ${targetModelFile}`); console.log(` - ${targetModelGenFile}`); // 检查源文件是否存在并移动 if (fs.existsSync(sourceModelFile)) { console.log(`Moving ${sourceModelFile} to ${targetModelFile}`); fs.copyFileSync(sourceModelFile, targetModelFile); fs.unlinkSync(sourceModelFile); } else { console.log(`WARNING: Source file not found: ${sourceModelFile}`); } if (fs.existsSync(sourceModelGenFile)) { console.log(`Moving ${sourceModelGenFile} to ${targetModelGenFile}`); fs.copyFileSync(sourceModelGenFile, targetModelGenFile); fs.unlinkSync(sourceModelGenFile); } else { console.log(`WARNING: Source file not found: ${sourceModelGenFile}`); } console.log(`Processing completed for table: ${table}`); } catch (error) { console.error(`ERROR processing table: ${table}`); console.error(error.message); console.error(error.stack); } } /** * 生成指定表列表的模型 * @param {string[]} tables 表名列表 * @param {object} config 配置信息 */ function generateModels(tables, config) { try { // 确保目录存在 ensureDirectoryExists(config.outputDir); ensureDirectoryExists(config.targetDir); if (tables.length === 0) { console.log('No tables specified for generation.'); return; } // 为每个表生成模型 for (const table of tables) { generateModelForTable(table, config); } console.log('========================================='); console.log('All models generated successfully.'); } catch (error) { console.error('ERROR in model generation:'); console.error(error.message); console.error(error.stack); process.exit(1); } } /** * 从数据库获取所有表名 * @param {string} dbUrl 数据库连接URL * @returns {Promise} 表名列表 */ async function getAllTablesFromDB(dbUrl) { try { // 解析数据库连接信息 const dbName = dbUrl.split('/').pop().split('?')[0]; console.log(`Fetching all tables from database: ${dbName}`); // 这里需要实现从数据库获取所有表的逻辑 // 由于需要依赖额外的库,这里只是示例 // 实际实现可能需要使用mysql2或其他数据库客户端库 // 模拟返回一些表名 return [ 'agent', 'agent_audit', 'agent_real_name', 'agent_active_stat', 'agent_closure', 'agent_commission', 'agent_commission_deduction', 'agent_link', 'agent_membership_config', 'agent_membership_recharge_order', 'agent_membership_user_config', 'agent_order', 'agent_platform_deduction', 'agent_product_config', 'agent_rewards', 'agent_wallet', 'agent_withdrawal', 'feature', 'global_notifications', 'order', 'product', 'product_feature', 'query', 'user', 'user_auth', 'example', 'authorization', 'authorization_face' ]; } catch (error) { console.error('Error fetching tables from database:', error.message); return []; } } /** * 显示配置信息 */ function showConfig() { console.log('========================================='); console.log('Current Configuration:'); console.log('\nModel Configuration:'); console.log(' Database URL:', modelConfig.dbUrl); console.log(' Output Directory:', modelConfig.outputDir); console.log(' Template Directory:', modelConfig.templateDir); console.log(' Target Directory:', modelConfig.targetDir); console.log(' Tables:'); modelConfig.tables.forEach(table => console.log(` - ${table}`)); if (modelConfig.disabledTables && modelConfig.disabledTables.length > 0) { console.log(' Disabled Tables:'); modelConfig.disabledTables.forEach(table => console.log(` - ${table}`)); } console.log('\nAPI Configuration:'); console.log(' API File:', apiConfig.apiFile); console.log(' Output Directory:', apiConfig.outputDir); console.log(' Template Directory:', apiConfig.templateDir); console.log(' Use Style:', apiConfig.useStyle ? 'Yes' : 'No'); console.log('========================================='); } /** * 保存配置到文件 * @param {object} config 配置对象 */ function saveConfig(config) { try { fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 4), 'utf8'); console.log('Configuration saved to config.json'); } catch (error) { console.error('Error saving configuration:', error.message); } } /** * 显示帮助信息 */ function showHelp() { console.log('Usage: node codegen.js [options]'); console.log('Commands:'); console.log(' model Generate database models'); console.log(' api Generate API code'); console.log(' config Show current configuration'); console.log(' help Show this help message'); console.log(''); console.log('Model Options:'); console.log(' --table Generate model for specific table'); console.log(' --tables Generate models for specific tables (comma-separated)'); console.log(' --exclude Exclude specific tables (comma-separated)'); console.log(' --all Generate models for all tables in database'); console.log(' --db-url Database connection URL'); console.log(' --template Template directory'); console.log(' --save Save specified tables to config.json'); console.log(''); console.log('API Options:'); console.log(' --api API definition file path'); console.log(' --dir Output directory'); console.log(' --template Template directory'); console.log(' --style Use goZero style'); console.log(''); console.log('Configuration:'); console.log(' Settings are loaded from config.json'); console.log(' Command line options override config file settings'); console.log(''); console.log('Examples:'); console.log(' node codegen.js model --table agent'); console.log(' node codegen.js model --tables agent,user,order'); console.log(' node codegen.js model --exclude user,order'); console.log(' node codegen.js model --all --exclude system_table'); console.log(' node codegen.js model --tables agent,user --save'); process.exit(0); } /** * 主函数 */ async function main() { // 解析命令行参数 const args = process.argv.slice(2); if (args.length === 0 || args[0] === 'help') { showHelp(); } const command = args[0]; // 显示配置信息 if (command === 'config') { showConfig(); return; } // 处理模型生成命令 if (command === 'model') { const config = { ...modelConfig }; let singleTable = null; let tablesToGenerate = [...config.tables]; let excludeTables = []; let shouldSaveConfig = false; let generateAllTables = false; // 处理其他参数 for (let i = 1; i < args.length; i++) { const arg = args[i]; if (arg === '--table' && i + 1 < args.length) { singleTable = args[++i]; tablesToGenerate = [singleTable]; } else if (arg === '--tables' && i + 1 < args.length) { const tableList = args[++i].split(',').map(t => t.trim()).filter(t => t); tablesToGenerate = tableList; } else if (arg === '--exclude' && i + 1 < args.length) { excludeTables = args[++i].split(',').map(t => t.trim()).filter(t => t); } else if (arg === '--all') { generateAllTables = true; } else if (arg === '--db-url' && i + 1 < args.length) { config.dbUrl = args[++i]; } else if (arg === '--template' && i + 1 < args.length) { config.templateDir = args[++i]; } else if (arg === '--save') { shouldSaveConfig = true; } } // 如果指定了--all参数,获取所有表名 if (generateAllTables) { tablesToGenerate = await getAllTablesFromDB(config.dbUrl); } // 排除指定的表 if (excludeTables.length > 0) { tablesToGenerate = tablesToGenerate.filter(table => !excludeTables.includes(table)); } // 保存配置 if (shouldSaveConfig) { const newConfig = { ...config }; newConfig.tables = tablesToGenerate; // 更新配置文件 if (fs.existsSync(CONFIG_FILE)) { const existingConfig = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); existingConfig.model = newConfig; saveConfig(existingConfig); } else { saveConfig({ model: newConfig, api: apiConfig }); } } // 生成单个表的模型或所有表的模型 if (singleTable) { generateModelForTable(singleTable, config); } else { generateModels(tablesToGenerate, config); } } // 处理API生成命令 else if (command === 'api') { const config = { ...apiConfig }; // 处理其他参数 for (let i = 1; i < args.length; i++) { const arg = args[i]; if (arg === '--api' && i + 1 < args.length) { config.apiFile = args[++i]; } else if (arg === '--dir' && i + 1 < args.length) { config.outputDir = args[++i]; } else if (arg === '--template' && i + 1 < args.length) { config.templateDir = args[++i]; } else if (arg === '--style') { config.useStyle = true; } } // 生成API代码 generateApi(config); } else { console.error(`Unknown command: ${command}`); showHelp(); } } // 执行主函数 if (require.main === module) { main().catch(err => { console.error('Error in main execution:', err); process.exit(1); }); } // 导出函数,以便其他脚本可以调用 module.exports = { generateModels, generateModelForTable, generateApi, showConfig, saveConfig, getAllTablesFromDB };