import '../core/models.dart'; import '../generators/documentation_generator.dart'; import '../generators/endpoint_code_generator.dart'; import '../generators/model_code_generator.dart'; import '../generators/retrofit_api_generator.dart'; import '../parsers/swagger_data_parser.dart'; import '../utils/file_utils.dart'; import 'base_command.dart'; /// Generate命令 /// 用于生成各种代码文件 class GenerateCommand extends BaseCommand { @override String get name => 'generate'; @override String get description => '生成API代码文件(模型、端点、文档等)'; @override String get usage => 'dart swagger_cli.dart generate [options]'; @override List get options => [ const CommandOption( name: 'endpoints', shortName: 'e', description: '生成API端点常量', type: OptionType.flag, ), const CommandOption( name: 'models', shortName: 'm', description: '生成数据模型', type: OptionType.flag, ), const CommandOption( name: 'docs', shortName: 'd', description: '生成API文档', type: OptionType.flag, ), const CommandOption( name: 'api', shortName: 'r', description: '生成Retrofit风格API接口', type: OptionType.flag, ), const CommandOption( name: 'split-by-tags', shortName: 't', description: '按tags分组生成多个API文件', type: OptionType.flag, ), const CommandOption( name: 'all', shortName: 'a', description: '生成所有文件(默认)', type: OptionType.flag, ), const CommandOption( name: 'simple', shortName: 's', description: '使用简洁版模型生成', type: OptionType.flag, ), const CommandOption( name: 'output-dir', shortName: 'o', description: '输出目录', type: OptionType.string, defaultValue: 'generator', ), ]; @override Future execute(List args) async { try { final parsedArgs = parseArguments(args); validateArguments(parsedArgs); await prepare(parsedArgs); // 解析Swagger文档 progress('正在解析Swagger文档...'); final parser = SwaggerDataParser(); final document = await parser.fetchAndParseSwaggerDocument(); // 解析生成选项 final options = _parseGenerateOptions(parsedArgs); final outputDir = parsedArgs.getOption('output-dir') ?? 'generator'; final fullOutputDir = FileUtils.getProjectRootGeneratorDir(); progress('输出目录: $fullOutputDir'); // 确保输出目录存在 await FileUtils.ensureDirectoryExists(fullOutputDir); int generatedFiles = 0; // 生成端点代码 if (options.generateEndpoints) { progress('正在生成API端点常量...'); final generator = EndpointCodeGenerator(document); final code = generator.generate(); final filePath = '$fullOutputDir/api_paths.dart'; await FileUtils.writeFile(filePath, code); success('API端点常量已保存到: $filePath'); generatedFiles++; } // 生成模型代码 if (options.generateModels) { progress('正在生成数据模型...'); final generator = ModelCodeGenerator( document, useSimpleModels: options.useSimpleModels, ); final modelsDir = '$fullOutputDir/api_models'; await FileUtils.ensureDirectoryExists(modelsDir); final modelFiles = generator.generateSeparateModelFiles(); for (final entry in modelFiles.entries) { final filePath = '$modelsDir/${entry.key}'; await FileUtils.writeFile(filePath, entry.value); success('模型文件已保存到: $filePath'); generatedFiles++; } } // 生成 Retrofit 风格的 API 接口 if (options.generateApi) { if (options.splitByTags) { progress('正在按tags分组生成Retrofit风格API接口...'); final generator = RetrofitApiGenerator( document, className: 'ApiClient', useRetrofit: true, useDio: true, splitByTags: true, ); // 确保参数实体类已生成 generator.ensureParameterEntitiesGenerated(); // 生成按 tags 分组的多个 API 文件 final tagApiFiles = generator.generateApiFilesByTags(); final apiDir = '$fullOutputDir/api'; await FileUtils.ensureDirectoryExists(apiDir); for (final entry in tagApiFiles.entries) { final fileName = entry.key; final code = entry.value; final filePath = '$apiDir/$fileName'; await FileUtils.writeFile(filePath, code); success('API接口文件已保存到: $filePath'); generatedFiles++; } // 生成主 API 文件 final mainCode = generator.generateMainApiFile(); final mainFilePath = '$apiDir/api_client.dart'; await FileUtils.writeFile(mainFilePath, mainCode); success('主API接口文件已保存到: $mainFilePath'); generatedFiles++; // 生成参数实体类文件 final parameterEntityFiles = generator.generateParameterEntityFiles(); if (parameterEntityFiles.isNotEmpty) { final modelsDir = '$fullOutputDir/api_models'; await FileUtils.ensureDirectoryExists(modelsDir); for (final entry in parameterEntityFiles.entries) { final filePath = '$modelsDir/${entry.key}'; await FileUtils.writeFile(filePath, entry.value); success('参数实体类文件已保存到: $filePath'); generatedFiles++; } } } else { progress('正在生成Retrofit风格API接口...'); final generator = RetrofitApiGenerator( document, className: 'ApiClient', useRetrofit: true, useDio: true, splitByTags: false, ); // 确保参数实体类已生成 generator.ensureParameterEntitiesGenerated(); final code = generator.generate(); final apiDir = '$fullOutputDir/api'; await FileUtils.ensureDirectoryExists(apiDir); final filePath = '$apiDir/api.dart'; await FileUtils.writeFile(filePath, code); success('Retrofit API接口已保存到: $filePath'); generatedFiles++; // 生成参数实体类文件 final parameterEntityFiles = generator.generateParameterEntityFiles(); if (parameterEntityFiles.isNotEmpty) { final modelsDir = '$fullOutputDir/api_models'; await FileUtils.ensureDirectoryExists(modelsDir); for (final entry in parameterEntityFiles.entries) { final filePath = '$modelsDir/${entry.key}'; await FileUtils.writeFile(filePath, entry.value); success('参数实体类文件已保存到: $filePath'); generatedFiles++; } } } } // 生成文档 if (options.generateDocs) { progress('正在生成API文档...'); final generator = DocumentationGenerator(document); final code = generator.generate(); final filePath = '$fullOutputDir/api_documentation.md'; await FileUtils.writeFile(filePath, code); success('API文档已保存到: $filePath'); generatedFiles++; } // 生成摘要 _generateSummary(document, fullOutputDir); success('代码生成完成!共生成 $generatedFiles 个文件'); return 0; } catch (e) { print('❌ 生成失败: $e'); return 1; } } /// 解析生成选项 GenerateOptions _parseGenerateOptions(ParsedArguments args) { final hasAnyFlag = args.hasOption('endpoints') || args.hasOption('models') || args.hasOption('docs') || args.hasOption('api'); return GenerateOptions( generateEndpoints: hasAnyFlag ? (args.getOption('endpoints') ?? false) : (args.getOption('all') ?? true), generateModels: hasAnyFlag ? (args.getOption('models') ?? false) : (args.getOption('all') ?? true), generateDocs: hasAnyFlag ? (args.getOption('docs') ?? false) : (args.getOption('all') ?? true), generateApi: hasAnyFlag ? (args.getOption('api') ?? false) : (args.getOption('all') ?? true), useSimpleModels: args.getOption('simple') ?? false, splitByTags: args.getOption('split-by-tags') ?? false, ); } /// 生成摘要信息 void _generateSummary(SwaggerDocument document, String outputDir) { final summary = StringBuffer(); summary.writeln('# 代码生成摘要'); summary.writeln(''); summary.writeln('**API标题**: ${document.title}'); summary.writeln('**API版本**: ${document.version}'); summary.writeln('**生成时间**: ${DateTime.now().toIso8601String()}'); summary.writeln(''); summary.writeln('## 统计信息'); summary.writeln('- 控制器数量: ${document.controllers.length}'); summary.writeln('- API路径数量: ${document.paths.length}'); summary.writeln('- 数据模型数量: ${document.models.length}'); summary.writeln(''); summary.writeln('## 控制器列表'); document.controllers.forEach((name, controller) { summary.writeln( '- **$name**: ${controller.description} (${controller.paths.length} 个路径)'); }); FileUtils.writeFile('$outputDir/SUMMARY.md', summary.toString()); } } /// 生成选项 class GenerateOptions { final bool generateEndpoints; final bool generateModels; final bool generateDocs; final bool generateApi; final bool useSimpleModels; final bool splitByTags; const GenerateOptions({ required this.generateEndpoints, required this.generateModels, required this.generateDocs, required this.generateApi, required this.useSimpleModels, required this.splitByTags, }); }