feat: update

This commit is contained in:
Max 2025-11-23 14:11:16 +08:00
parent 53f89940ed
commit d6a31d5a24
20 changed files with 165 additions and 89 deletions

View File

@ -27,4 +27,3 @@ export 'pipeline/validate/enhanced_validator.dart';
// --- Utilities --- // --- Utilities ---
export 'utils/logger.dart'; export 'utils/logger.dart';
export 'utils/path_resolver.dart'; export 'utils/path_resolver.dart';
export 'utils/string_utils.dart';

View File

@ -1,7 +1,7 @@
import 'package:swagger_generator_flutter/core/config.dart'; import 'package:swagger_generator_flutter/core/config.dart';
import 'package:swagger_generator_flutter/core/exceptions.dart'; import 'package:swagger_generator_flutter/core/exceptions.dart';
import 'package:swagger_generator_flutter/core/models.dart'; import 'package:swagger_generator_flutter/core/models.dart';
import 'package:swagger_generator_flutter/utils/string_utils.dart'; import 'package:swagger_generator_flutter/utils/string_helper.dart';
/// ///
/// ///
@ -16,7 +16,7 @@ abstract class BaseGenerator {
/// [description] /// [description]
/// [fileName] /// [fileName]
String generateFileHeader(String description, {String? fileName}) { String generateFileHeader(String description, {String? fileName}) {
final header = StringUtils.generateFileHeader( final header = StringHelper.generateFileHeader(
description, description,
SwaggerConfig.swaggerJsonUrls.isNotEmpty SwaggerConfig.swaggerJsonUrls.isNotEmpty
? SwaggerConfig.swaggerJsonUrls.first ? SwaggerConfig.swaggerJsonUrls.first
@ -105,7 +105,7 @@ abstract class ModelGenerator extends BaseGenerator {
throw CodeGenerationException('模型不是枚举类型', generatorType: generatorType); throw CodeGenerationException('模型不是枚举类型', generatorType: generatorType);
} }
final className = StringUtils.generateClassName(model.name); final className = StringHelper.generateClassName(model.name);
final enumType = model.enumType?.value ?? 'string'; final enumType = model.enumType?.value ?? 'string';
final valueType = final valueType =
enumType == 'integer' || enumType == 'number' ? 'int' : 'String'; enumType == 'integer' || enumType == 'number' ? 'int' : 'String';
@ -116,7 +116,7 @@ abstract class ModelGenerator extends BaseGenerator {
// //
if (model.description.isNotEmpty) { if (model.description.isNotEmpty) {
buffer.writeln(StringUtils.generateComment(model.description)); buffer.writeln(StringHelper.generateComment(model.description));
} }
buffer.writeln('enum $className {'); buffer.writeln('enum $className {');
@ -124,7 +124,7 @@ abstract class ModelGenerator extends BaseGenerator {
// //
for (var i = 0; i < model.enumValues.length; i++) { for (var i = 0; i < model.enumValues.length; i++) {
final value = model.enumValues[i]; final value = model.enumValues[i];
final enumName = StringUtils.generateEnumValueName(value, i); final enumName = StringHelper.generateEnumValueName(value, i);
final enumLine = enumType == 'integer' || enumType == 'number' final enumLine = enumType == 'integer' || enumType == 'number'
? ' $enumName($value),' ? ' $enumName($value),'
: " $enumName('$value'),"; : " $enumName('$value'),";
@ -226,7 +226,7 @@ abstract class ModelGenerator extends BaseGenerator {
return 'Map<String, dynamic>'; return 'Map<String, dynamic>';
case PropertyType.reference: case PropertyType.reference:
return property.reference != null return property.reference != null
? StringUtils.generateClassName(property.reference!) ? StringHelper.generateClassName(property.reference!)
: 'dynamic'; : 'dynamic';
case PropertyType.file: case PropertyType.file:
return 'dynamic'; return 'dynamic';
@ -248,7 +248,7 @@ abstract class ModelGenerator extends BaseGenerator {
items.name != 'integer' && items.name != 'integer' &&
items.name != 'number' && items.name != 'number' &&
items.name != 'boolean') { items.name != 'boolean') {
return StringUtils.generateClassName(items.name); return StringHelper.generateClassName(items.name);
} }
// Dart类型 // Dart类型

View File

@ -11,14 +11,14 @@ String _generateModelCodeWithoutImports(
} }
String _generateEnumCodeWithoutImports(ApiModel model) { String _generateEnumCodeWithoutImports(ApiModel model) {
final className = StringUtils.generateClassName(model.name); final className = StringHelper.generateClassName(model.name);
final enumType = model.enumType?.value ?? 'string'; final enumType = model.enumType?.value ?? 'string';
final valueType = final valueType =
enumType == 'integer' || enumType == 'number' ? 'int' : 'String'; enumType == 'integer' || enumType == 'number' ? 'int' : 'String';
final buffer = StringBuffer(); final buffer = StringBuffer();
if (model.description.isNotEmpty) { if (model.description.isNotEmpty) {
buffer.writeln(StringUtils.generateComment(model.description)); buffer.writeln(StringHelper.generateComment(model.description));
} }
buffer buffer
@ -27,7 +27,7 @@ String _generateEnumCodeWithoutImports(ApiModel model) {
for (var i = 0; i < model.enumValues.length; i++) { for (var i = 0; i < model.enumValues.length; i++) {
final value = model.enumValues[i]; final value = model.enumValues[i];
final enumName = StringUtils.generateEnumValueName(value, i); final enumName = StringHelper.generateEnumValueName(value, i);
final enumLine = enumType == 'integer' || enumType == 'number' final enumLine = enumType == 'integer' || enumType == 'number'
? ' $enumName($value),' ? ' $enumName($value),'
: " $enumName('$value'),"; : " $enumName('$value'),";
@ -73,10 +73,10 @@ String _generateAnnotatedModelCodeWithoutImports(
ModelCodeGenerator generator, ModelCodeGenerator generator,
ApiModel model, ApiModel model,
) { ) {
final className = StringUtils.generateClassName(model.name); final className = StringHelper.generateClassName(model.name);
final buffer = StringBuffer(); final buffer = StringBuffer();
final partFileName = StringUtils.generateFileName(model.name); final partFileName = StringHelper.generateFileName(model.name);
final freezedPart = partFileName.replaceAll('.dart', '.freezed.dart'); final freezedPart = partFileName.replaceAll('.dart', '.freezed.dart');
final generatedPart = partFileName.replaceAll('.dart', '.g.dart'); final generatedPart = partFileName.replaceAll('.dart', '.g.dart');
buffer buffer
@ -85,7 +85,7 @@ String _generateAnnotatedModelCodeWithoutImports(
..writeln(); ..writeln();
if (model.description.isNotEmpty) { if (model.description.isNotEmpty) {
buffer.writeln(StringUtils.generateComment(model.description)); buffer.writeln(StringHelper.generateComment(model.description));
} }
buffer buffer
@ -100,11 +100,11 @@ String _generateAnnotatedModelCodeWithoutImports(
property.format != 'date'; property.format != 'date';
final hasDefaultValue = property.defaultValue != null || isNormalString; final hasDefaultValue = property.defaultValue != null || isNormalString;
final nullable = hasDefaultValue ? '' : (property.nullable ? '?' : ''); final nullable = hasDefaultValue ? '' : (property.nullable ? '?' : '');
final dartPropName = StringUtils.toDartPropertyName(propName); final dartPropName = StringHelper.toDartPropertyName(propName);
if (property.description.isNotEmpty) { if (property.description.isNotEmpty) {
buffer.writeln( buffer.writeln(
' ${StringUtils.generateComment(property.description)}', ' ${StringHelper.generateComment(property.description)}',
); );
} }
@ -179,7 +179,7 @@ String _generateSubDirectoryIndexFile(
..sort((a, b) => a.name.compareTo(b.name)); ..sort((a, b) => a.name.compareTo(b.name));
for (final model in sortedModels) { for (final model in sortedModels) {
final fileName = StringUtils.generateFileName(model.name); final fileName = StringHelper.generateFileName(model.name);
buffer.writeln("export '$fileName';"); buffer.writeln("export '$fileName';");
} }

View File

@ -12,7 +12,7 @@ Map<String, String> buildSeparateModelFiles(ModelCodeGenerator generator) {
final subDir = _getModelSubDirectory(model); final subDir = _getModelSubDirectory(model);
modelsByDirectory.putIfAbsent(subDir, () => []).add(model); modelsByDirectory.putIfAbsent(subDir, () => []).add(model);
final fileName = StringUtils.generateFileName(model.name); final fileName = StringHelper.generateFileName(model.name);
final filePath = '$subDir/$fileName'; final filePath = '$subDir/$fileName';
final content = buildSingleModelFile(generator, model, fileName: fileName); final content = buildSingleModelFile(generator, model, fileName: fileName);
files[filePath] = content; files[filePath] = content;
@ -38,7 +38,7 @@ String buildSingleModelFile(
..writeln( ..writeln(
generator.generateFileHeader( generator.generateFileHeader(
'${model.name} 模型定义', '${model.name} 模型定义',
fileName: fileName ?? StringUtils.generateFileName(model.name), fileName: fileName ?? StringHelper.generateFileName(model.name),
), ),
) )
..writeln(); ..writeln();

View File

@ -24,7 +24,7 @@ String _getPaginationItemType(ApiModel items) {
items.name != 'integer' && items.name != 'integer' &&
items.name != 'number' && items.name != 'number' &&
items.name != 'boolean') { items.name != 'boolean') {
return StringUtils.generateClassName(items.name); return StringHelper.generateClassName(items.name);
} }
switch (items.name) { switch (items.name) {

View File

@ -1,7 +1,7 @@
import 'package:swagger_generator_flutter/core/config.dart'; import 'package:swagger_generator_flutter/core/config.dart';
import 'package:swagger_generator_flutter/core/models.dart'; import 'package:swagger_generator_flutter/core/models.dart';
import 'package:swagger_generator_flutter/pipeline/generate/impl/base_generator.dart'; import 'package:swagger_generator_flutter/pipeline/generate/impl/base_generator.dart';
import 'package:swagger_generator_flutter/utils/string_utils.dart'; import 'package:swagger_generator_flutter/utils/string_helper.dart';
part 'model/model_content_builders.dart'; part 'model/model_content_builders.dart';
part 'model/model_file_writers.dart'; part 'model/model_file_writers.dart';

View File

@ -6,7 +6,7 @@ mixin RetrofitApiParameterEntities {
/// ///
String _generateParameterEntityClassName(ApiPath path) { String _generateParameterEntityClassName(ApiPath path) {
final methodName = _g._generateSimpleMethodName(path); final methodName = _g._generateSimpleMethodName(path);
return '${StringUtils.toPascalCase(methodName)}Parameters'; return '${StringHelper.toPascalCase(methodName)}Parameters';
} }
/// ///
@ -19,7 +19,7 @@ mixin RetrofitApiParameterEntities {
..writeln( ..writeln(
_g.generateFileHeader( _g.generateFileHeader(
'参数实体类 - $className', '参数实体类 - $className',
fileName: '${StringUtils.toSnakeCase(className)}.dart', fileName: '${StringHelper.toSnakeCase(className)}.dart',
), ),
) )
..writeln( ..writeln(
@ -28,12 +28,12 @@ mixin RetrofitApiParameterEntities {
..writeln() ..writeln()
..writeln("import 'package:json_annotation/json_annotation.dart';") ..writeln("import 'package:json_annotation/json_annotation.dart';")
..writeln() ..writeln()
..writeln("part '${StringUtils.toSnakeCase(className)}.g.dart';") ..writeln("part '${StringHelper.toSnakeCase(className)}.g.dart';")
..writeln() ..writeln()
..writeln('@JsonSerializable(checked: true, includeIfNull: false)') ..writeln('@JsonSerializable(checked: true, includeIfNull: false)')
..writeln('class $className {'); ..writeln('class $className {');
for (final param in queryParams) { for (final param in queryParams) {
final dartName = StringUtils.toDartPropertyName(param.name); final dartName = StringHelper.toDartPropertyName(param.name);
final dartType = _g._getDartType(param.type); final dartType = _g._getDartType(param.type);
final nullable = param.required ? '' : '?'; final nullable = param.required ? '' : '?';
@ -53,7 +53,7 @@ mixin RetrofitApiParameterEntities {
buffer.writeln(' const $className({'); buffer.writeln(' const $className({');
for (final param in queryParams) { for (final param in queryParams) {
final dartName = StringUtils.toDartPropertyName(param.name); final dartName = StringHelper.toDartPropertyName(param.name);
final required = param.required ? 'required ' : ''; final required = param.required ? 'required ' : '';
buffer.writeln(' ${required}this.$dartName,'); buffer.writeln(' ${required}this.$dartName,');
} }
@ -73,7 +73,7 @@ mixin RetrofitApiParameterEntities {
..writeln(' Map<String, dynamic> toQueryMap() {') ..writeln(' Map<String, dynamic> toQueryMap() {')
..writeln(' final map = <String, dynamic>{};'); ..writeln(' final map = <String, dynamic>{};');
for (final param in queryParams) { for (final param in queryParams) {
final dartName = StringUtils.toDartPropertyName(param.name); final dartName = StringHelper.toDartPropertyName(param.name);
buffer.writeln( buffer.writeln(
" if ($dartName != null) map['${param.name}'] = $dartName;", " if ($dartName != null) map['${param.name}'] = $dartName;",
); );
@ -96,7 +96,7 @@ mixin RetrofitApiParameterEntities {
for (final entry in _generatedParameterEntities.entries) { for (final entry in _generatedParameterEntities.entries) {
final className = entry.key; final className = entry.key;
final content = entry.value; final content = entry.value;
final fileName = StringUtils.generateFileName(className); final fileName = StringHelper.generateFileName(className);
files[fileName] = content; files[fileName] = content;
} }

View File

@ -13,7 +13,7 @@ mixin RetrofitApiParameters {
for (final param in pathParams) { for (final param in pathParams) {
parameters.add( parameters.add(
ApiMethodParameter( ApiMethodParameter(
name: StringUtils.toDartPropertyName(param.name), name: StringHelper.toDartPropertyName(param.name),
type: _getDartType(param.type), type: _getDartType(param.type),
annotation: _g.useRetrofit ? "@Path('${param.name}')" : '', annotation: _g.useRetrofit ? "@Path('${param.name}')" : '',
required: param.required, required: param.required,
@ -46,7 +46,7 @@ mixin RetrofitApiParameters {
final nullable = param.required ? '' : '?'; final nullable = param.required ? '' : '?';
parameters.add( parameters.add(
ApiMethodParameter( ApiMethodParameter(
name: StringUtils.toDartPropertyName(param.name), name: StringHelper.toDartPropertyName(param.name),
type: '${_getDartType(param.type)}$nullable', type: '${_getDartType(param.type)}$nullable',
annotation: _g.useRetrofit ? "@Query('${param.name}')" : '', annotation: _g.useRetrofit ? "@Query('${param.name}')" : '',
required: param.required, required: param.required,
@ -64,7 +64,7 @@ mixin RetrofitApiParameters {
final bodyType = _inferRequestBodyType(path); final bodyType = _inferRequestBodyType(path);
parameters.add( parameters.add(
ApiMethodParameter( ApiMethodParameter(
name: StringUtils.toDartPropertyName( name: StringHelper.toDartPropertyName(
param.name.isNotEmpty ? param.name : 'request', param.name.isNotEmpty ? param.name : 'request',
), ),
type: bodyType, type: bodyType,

View File

@ -36,7 +36,7 @@ mixin RetrofitApiSchemaComposition {
if (schemaData[r'$ref'] != null) { if (schemaData[r'$ref'] != null) {
final ref = schemaData[r'$ref'] as String; final ref = schemaData[r'$ref'] as String;
final refName = ref.split('/').last; final refName = ref.split('/').last;
return StringUtils.generateClassName(refName); return StringHelper.generateClassName(refName);
} }
if (schemaData['type'] != null) { if (schemaData['type'] != null) {
@ -67,7 +67,7 @@ mixin RetrofitApiSchemaComposition {
if (schemaData is Map<String, dynamic> && schemaData[r'$ref'] != null) { if (schemaData is Map<String, dynamic> && schemaData[r'$ref'] != null) {
final ref = schemaData[r'$ref'] as String; final ref = schemaData[r'$ref'] as String;
final refName = ref.split('/').last; final refName = ref.split('/').last;
refTypes.add(StringUtils.generateClassName(refName)); refTypes.add(StringHelper.generateClassName(refName));
} }
} }
@ -104,7 +104,7 @@ mixin RetrofitApiSchemaComposition {
for (final value in mapping.values) { for (final value in mapping.values) {
if (value is String) { if (value is String) {
final refName = value.split('/').last; final refName = value.split('/').last;
mappedTypes.add(StringUtils.generateClassName(refName)); mappedTypes.add(StringHelper.generateClassName(refName));
} }
} }

View File

@ -50,7 +50,7 @@ mixin RetrofitApiSchema {
if (schema[r'$ref'] != null) { if (schema[r'$ref'] != null) {
final ref = schema[r'$ref'] as String; final ref = schema[r'$ref'] as String;
final refName = ref.split('/').last; final refName = ref.split('/').last;
return StringUtils.generateClassName(refName); return StringHelper.generateClassName(refName);
} }
if (schema['type'] != null) { if (schema['type'] != null) {
@ -110,7 +110,7 @@ mixin RetrofitApiSchema {
/// ///
String _generateSimpleMethodName(ApiPath path) { String _generateSimpleMethodName(ApiPath path) {
if (path.operationId.isNotEmpty) { if (path.operationId.isNotEmpty) {
return StringUtils.toCamelCase(path.operationId); return StringHelper.toCamelCase(path.operationId);
} }
final pathParts = path.path final pathParts = path.path
@ -124,7 +124,7 @@ mixin RetrofitApiSchema {
final lastPart = pathParts.last.replaceAll(RegExp(r'\W+'), ''); final lastPart = pathParts.last.replaceAll(RegExp(r'\W+'), '');
final method = path.method.value.toLowerCase(); final method = path.method.value.toLowerCase();
final pascalPart = StringUtils.toPascalCase(lastPart); final pascalPart = StringHelper.toPascalCase(lastPart);
final methodName = '$method$pascalPart'; final methodName = '$method$pascalPart';
return methodName; return methodName;

View File

@ -6,7 +6,7 @@ mixin RetrofitApiTemplateData {
List<String> _getMainImports() { List<String> _getMainImports() {
final tagGroups = _g._groupPathsByTags(); final tagGroups = _g._groupPathsByTags();
final tagImports = tagGroups.keys.map((tag) { final tagImports = tagGroups.keys.map((tag) {
final fileName = StringUtils.generateFileName(tag); final fileName = StringHelper.generateFileName(tag);
return "import '$fileName.dart';"; return "import '$fileName.dart';";
}).toList(); }).toList();
@ -22,8 +22,8 @@ mixin RetrofitApiTemplateData {
'apis': tagGroups.entries.map((entry) { 'apis': tagGroups.entries.map((entry) {
final tagName = entry.key; final tagName = entry.key;
return { return {
'name': StringUtils.toCamelCase(tagName), 'name': StringHelper.toCamelCase(tagName),
'className': '${StringUtils.toPascalCase(tagName)}Api', 'className': '${StringHelper.toPascalCase(tagName)}Api',
}; };
}).toList(), }).toList(),
}; };
@ -34,7 +34,7 @@ mixin RetrofitApiTemplateData {
_g.document.servers.isNotEmpty ? _g.document.servers.first.url : ''; _g.document.servers.isNotEmpty ? _g.document.servers.first.url : '';
var fileName = ''; var fileName = '';
if (_g.className.isNotEmpty) { if (_g.className.isNotEmpty) {
fileName = StringUtils.generateFileName(_g.className); fileName = StringHelper.generateFileName(_g.className);
} }
return { return {

View File

@ -2,7 +2,7 @@ import 'package:swagger_generator_flutter/core/config_repository.dart';
import 'package:swagger_generator_flutter/core/models.dart'; import 'package:swagger_generator_flutter/core/models.dart';
import 'package:swagger_generator_flutter/core/template_renderer.dart'; import 'package:swagger_generator_flutter/core/template_renderer.dart';
import 'package:swagger_generator_flutter/pipeline/generate/impl/base_generator.dart'; import 'package:swagger_generator_flutter/pipeline/generate/impl/base_generator.dart';
import 'package:swagger_generator_flutter/utils/string_utils.dart'; import 'package:swagger_generator_flutter/utils/string_helper.dart';
part 'retrofit_api/api_grouping.dart'; part 'retrofit_api/api_grouping.dart';
part 'retrofit_api/api_method_parameter.dart'; part 'retrofit_api/api_method_parameter.dart';
@ -108,8 +108,8 @@ class RetrofitApiGenerator extends BaseGenerator
final tagName = entry.key; final tagName = entry.key;
final paths = entry.value; final paths = entry.value;
// Use ${tagName}Api to match old behavior (user -> user_api.dart) // Use ${tagName}Api to match old behavior (user -> user_api.dart)
final fileName = StringUtils.generateFileName('${tagName}Api'); final fileName = StringHelper.generateFileName('${tagName}Api');
final apiClassName = '${StringUtils.toPascalCase(tagName)}Api'; final apiClassName = '${StringHelper.toPascalCase(tagName)}Api';
final data = _buildApiClassData(paths); final data = _buildApiClassData(paths);
data['className'] = apiClassName; data['className'] = apiClassName;

View File

@ -8,7 +8,7 @@ import 'package:swagger_generator_flutter/utils/cache_manager.dart';
import 'package:swagger_generator_flutter/utils/logger.dart'; import 'package:swagger_generator_flutter/utils/logger.dart';
import 'package:swagger_generator_flutter/utils/performance_monitor.dart'; import 'package:swagger_generator_flutter/utils/performance_monitor.dart';
import 'package:swagger_generator_flutter/utils/reference_resolver.dart'; import 'package:swagger_generator_flutter/utils/reference_resolver.dart';
import 'package:swagger_generator_flutter/utils/string_utils.dart'; import 'package:swagger_generator_flutter/utils/string_helper.dart';
/// Swagger数据解析器 /// Swagger数据解析器
/// Swagger JSON文档并提取相关信息 /// Swagger JSON文档并提取相关信息
@ -390,7 +390,7 @@ class SwaggerDataParser {
} }
// //
return StringUtils.generateClassName(swaggerType); return StringHelper.generateClassName(swaggerType);
} }
} }

View File

@ -4,7 +4,8 @@ import 'package:logging/logging.dart';
import 'package:swagger_generator_flutter/commands/base_command.dart'; import 'package:swagger_generator_flutter/commands/base_command.dart';
import 'package:swagger_generator_flutter/commands/generate_command.dart'; import 'package:swagger_generator_flutter/commands/generate_command.dart';
import 'package:swagger_generator_flutter/core/config.dart'; import 'package:swagger_generator_flutter/core/config.dart';
import 'package:swagger_generator_flutter/utils/string_utils.dart'; import 'package:swagger_generator_flutter/utils/string_helper.dart';
import 'package:swagger_generator_flutter/utils/string_utils/index.dart';
/// Swagger CLI /// Swagger CLI
/// 使CLI工具 /// 使CLI工具
@ -78,7 +79,9 @@ class SwaggerCLI {
if (exitCode == 0) { if (exitCode == 0) {
_logger _logger
..info('') ..info('')
..info('⏱️ 执行时间: ${StringUtils.formatDuration(stopwatch.elapsed)}'); ..info(
'⏱️ 执行时间: ${StringHelper.formatDuration(stopwatch.elapsed)}',
);
} }
return exitCode; return exitCode;

View File

@ -7,5 +7,3 @@ export 'core/error_reporter.dart';
// //
export 'core/models.dart'; export 'core/models.dart';
export 'core/performance_parser.dart'; export 'core/performance_parser.dart';
//
export 'utils/string_utils.dart';

View File

@ -0,0 +1,50 @@
/// API naming utilities for endpoint and controller name generation
library;
import 'package:swagger_generator_flutter/core/models.dart';
import 'package:swagger_generator_flutter/utils/string_utils/naming_converter.dart';
/// API naming utilities
class ApiNamingUtils {
/// Generate endpoint name from path and operationId
static String generateEndpointName(String path, String? operationId) {
// If operationId exists, use it with priority
if (operationId != null && operationId.isNotEmpty) {
return NamingConverter.toCamelCase(operationId);
}
// Remove version prefix from path
var cleanPath = path.replaceFirst('/api/v1', '');
// Remove leading slash
if (cleanPath.startsWith('/')) {
cleanPath = cleanPath.substring(1);
}
// Convert path to camelCase
final parts = cleanPath.split('/');
if (parts.length >= 2) {
final controller = parts[0];
final action = parts[1];
return NamingConverter.toCamelCase('${controller}_$action');
}
return NamingConverter.toCamelCase(cleanPath.replaceAll('/', '_'));
}
/// Extract controller name from API path
static String extractControllerName(ApiPath path) {
// Extract controller name from tags
if (path.tags.isNotEmpty) {
return path.tags.first;
}
// Extract controller name from path
final pathParts = path.path.split('/');
if (pathParts.length > 1) {
return NamingConverter.toPascalCase(pathParts[1]);
}
return 'General';
}
}

View File

@ -1,6 +1,6 @@
import 'dart:collection'; import 'dart:collection';
import 'package:swagger_generator_flutter/utils/string_utils.dart'; import 'package:swagger_generator_flutter/utils/string_utils/index.dart';
/// ///
/// ///
@ -115,7 +115,7 @@ class CacheStats {
'memoryItems: $memoryItems, ' 'memoryItems: $memoryItems, '
'diskItems: $diskItems, ' 'diskItems: $diskItems, '
'hitRate: ${(hitRate * 100).toStringAsFixed(1)}%, ' 'hitRate: ${(hitRate * 100).toStringAsFixed(1)}%, '
'totalSize: ${StringUtils.formatBytes(totalSize)}' 'totalSize: ${FormattingUtils.formatBytes(totalSize)}'
'}'; '}';
} }

View File

@ -5,22 +5,24 @@
/// - NamingConverter: camelCase, PascalCase, snake_case /// - NamingConverter: camelCase, PascalCase, snake_case
/// - TextCleaner: /// - TextCleaner:
/// - TemplateService: /// - TemplateService:
/// - FormattingUtils:
/// ///
/// # /// #
/// ```dart /// ```dart
/// // snake_case camelCase /// // snake_case camelCase
/// StringUtils.toDartPropertyName('user_id'); // userId /// StringHelper.toDartPropertyName('user_id'); // userId
/// // /// //
/// StringUtils.toDartPropertyName('user-id'); // userId /// StringHelper.toDartPropertyName('user-id'); // userId
/// // /// //
/// StringUtils.toDartPropertyName('1st_field'); // n1stField /// StringHelper.toDartPropertyName('1st_field'); // n1stField
/// // /// //
/// StringUtils.generateComment('API description'); // /// API description /// StringHelper.generateComment('API description'); // /// API description
/// ``` /// ```
/// ///
library; library;
import 'package:swagger_generator_flutter/core/models.dart'; import 'package:swagger_generator_flutter/core/models.dart';
import 'package:swagger_generator_flutter/utils/string_utils/formatting_utils.dart';
import 'package:swagger_generator_flutter/utils/string_utils/naming_converter.dart'; import 'package:swagger_generator_flutter/utils/string_utils/naming_converter.dart';
import 'package:swagger_generator_flutter/utils/string_utils/template_service.dart'; import 'package:swagger_generator_flutter/utils/string_utils/template_service.dart';
import 'package:swagger_generator_flutter/utils/string_utils/text_cleaner.dart'; import 'package:swagger_generator_flutter/utils/string_utils/text_cleaner.dart';
@ -28,7 +30,7 @@ import 'package:swagger_generator_flutter/utils/string_utils/text_cleaner.dart';
/// - /// -
/// ///
/// API /// API
class StringUtils { class StringHelper {
// ==================== (NamingConverter) ==================== // ==================== (NamingConverter) ====================
/// camelCase /// camelCase
static String toCamelCase(String input) => NamingConverter.toCamelCase(input); static String toCamelCase(String input) => NamingConverter.toCamelCase(input);
@ -77,10 +79,8 @@ class StringUtils {
static String escapeString(String input) => TextCleaner.escapeString(input); static String escapeString(String input) => TextCleaner.escapeString(input);
/// ///
static String indent(String text, int spaces) { static String indent(String text, int spaces) =>
final indentation = ' ' * spaces; FormattingUtils.indent(text, spaces);
return text.split('\n').map((line) => '$indentation$line').join('\n');
}
/// ///
static String truncate(String text, int maxLength, {String suffix = '...'}) => static String truncate(String text, int maxLength, {String suffix = '...'}) =>
@ -111,9 +111,21 @@ class StringUtils {
); );
} }
// ==================== ==================== // ==================== (FormattingUtils) ====================
///
static String formatBytes(int bytes) => FormattingUtils.formatBytes(bytes);
///
static String formatDuration(Duration duration) =>
FormattingUtils.formatDuration(duration);
// ==================== ====================
// ApiNamingUtils
/// ///
/// @deprecated 使 ApiNamingUtils.generateEndpointName
@Deprecated('Use ApiNamingUtils.generateEndpointName instead')
static String generateEndpointName(String path, String? operationId) { static String generateEndpointName(String path, String? operationId) {
// operationId使 // operationId使
if (operationId != null && operationId.isNotEmpty) { if (operationId != null && operationId.isNotEmpty) {
@ -140,6 +152,8 @@ class StringUtils {
} }
/// ///
/// @deprecated 使 ApiNamingUtils.extractControllerName
@Deprecated('Use ApiNamingUtils.extractControllerName instead')
static String extractControllerName(ApiPath path) { static String extractControllerName(ApiPath path) {
// tags // tags
if (path.tags.isNotEmpty) { if (path.tags.isNotEmpty) {
@ -154,31 +168,4 @@ class StringUtils {
return 'General'; return 'General';
} }
///
static String cleanPath(String path) {
//
return path;
}
// ==================== ====================
///
static String formatBytes(int bytes) {
if (bytes < 1024) return '${bytes}B';
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)}KB';
if (bytes < 1024 * 1024 * 1024) {
return '${(bytes / (1024 * 1024)).toStringAsFixed(1)}MB';
}
return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(1)}GB';
}
///
static String formatDuration(Duration duration) {
if (duration.inMilliseconds >= 1000) {
return '${(duration.inMilliseconds / 1000).toStringAsFixed(2)}';
} else {
return '${duration.inMilliseconds}毫秒';
}
}
} }

View File

@ -0,0 +1,30 @@
/// Formatting utilities for various data types
library;
/// Formatting utilities for bytes, durations, and text indentation
class FormattingUtils {
/// Indent text by specified number of spaces
static String indent(String text, int spaces) {
final indentation = ' ' * spaces;
return text.split('\n').map((line) => '$indentation$line').join('\n');
}
/// Format byte size to human-readable string
static String formatBytes(int bytes) {
if (bytes < 1024) return '${bytes}B';
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)}KB';
if (bytes < 1024 * 1024 * 1024) {
return '${(bytes / (1024 * 1024)).toStringAsFixed(1)}MB';
}
return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(1)}GB';
}
/// Format duration to human-readable string
static String formatDuration(Duration duration) {
if (duration.inMilliseconds >= 1000) {
return '${(duration.inMilliseconds / 1000).toStringAsFixed(2)}';
} else {
return '${duration.inMilliseconds}毫秒';
}
}
}

View File

@ -0,0 +1,9 @@
/// String utilities - unified export
///
/// This file provides a single export point for all string utilities
library;
export 'formatting_utils.dart';
export 'naming_converter.dart';
export 'template_service.dart';
export 'text_cleaner.dart';