Complete OpenAPI 3.0/3.1 generation, diagnostics, lifecycle safety, enum and naming mappings, bilingual documentation, examples, and pub.dev release validation.
175 lines
4.8 KiB
Dart
175 lines
4.8 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:args/args.dart';
|
|
import 'package:koi_swagger_parser/koi_swagger_parser.dart';
|
|
|
|
Future<void> main(List<String> arguments) async {
|
|
final parser = ArgParser()
|
|
..addFlag('help', abbr: 'h', negatable: false, help: 'Show command help.');
|
|
|
|
final generateParser = ArgParser()
|
|
..addFlag(
|
|
'help',
|
|
abbr: 'h',
|
|
negatable: false,
|
|
help: 'Show help for the generate command.',
|
|
)
|
|
..addFlag(
|
|
'all',
|
|
abbr: 'a',
|
|
negatable: false,
|
|
help:
|
|
'Generate all resources. Retained for compatibility with the '
|
|
'legacy command.',
|
|
)
|
|
..addOption(
|
|
'config',
|
|
abbr: 'c',
|
|
help: 'Path to the YAML configuration file.',
|
|
valueHelp: 'path',
|
|
)
|
|
..addOption(
|
|
'cwd',
|
|
help: 'Working directory used to resolve project-relative paths.',
|
|
valueHelp: 'directory',
|
|
)
|
|
..addFlag(
|
|
'dry-run',
|
|
negatable: false,
|
|
help: 'Parse and render without writing or deleting files.',
|
|
)
|
|
..addFlag(
|
|
'watch',
|
|
negatable: false,
|
|
help: 'Start build_runner watch after generation.',
|
|
)
|
|
..addFlag(
|
|
'verbose',
|
|
abbr: 'v',
|
|
negatable: false,
|
|
help: 'Print detailed diagnostics and stack traces.',
|
|
);
|
|
parser.addCommand('generate', generateParser);
|
|
|
|
late final ArgResults result;
|
|
try {
|
|
result = parser.parse(arguments);
|
|
} on FormatException catch (error) {
|
|
stderr.writeln('Error: ${error.message}');
|
|
stderr.writeln();
|
|
stderr.writeln(_usage(parser));
|
|
exitCode = 64;
|
|
return;
|
|
}
|
|
|
|
if ((result['help'] as bool?) ?? false) {
|
|
stdout.writeln(_usage(parser));
|
|
return;
|
|
}
|
|
|
|
final command = result.command;
|
|
if (command == null) {
|
|
stdout.writeln(_usage(parser));
|
|
return;
|
|
}
|
|
if (command.name == 'generate') {
|
|
if ((command['help'] as bool?) ?? false) {
|
|
stdout.writeln(_generateUsage(generateParser));
|
|
return;
|
|
}
|
|
await _runGenerate(command, generateParser);
|
|
return;
|
|
}
|
|
|
|
stdout.writeln(_usage(parser));
|
|
}
|
|
|
|
Future<void> _runGenerate(ArgResults result, ArgParser parser) async {
|
|
final generator = const KoiSwaggerParser();
|
|
try {
|
|
final summary = await generator.generate(
|
|
configPath: result['config'] as String?,
|
|
workingDirectory: result['cwd'] as String?,
|
|
dryRun: result['dry-run'] as bool? ?? false,
|
|
verbose: result['verbose'] as bool? ?? false,
|
|
buildRunnerWatch: result['watch'] as bool? ?? false,
|
|
);
|
|
|
|
for (final diagnostic in summary.diagnostics) {
|
|
if (diagnostic.severity == DiagnosticSeverity.info &&
|
|
!(result['verbose'] as bool? ?? false)) {
|
|
continue;
|
|
}
|
|
stderr.writeln('[koi_swagger_parser] ${diagnostic.format()}');
|
|
}
|
|
if (summary.dryRun) {
|
|
stdout.writeln(
|
|
'[koi_swagger_parser] dry-run: '
|
|
'${summary.wouldWriteFiles.length} file(s) would be written, '
|
|
'${summary.wouldDeleteFiles.length} stale file(s) would be deleted; '
|
|
'${summary.operationsCount} operation(s), '
|
|
'${summary.modelsCount} model(s).',
|
|
);
|
|
} else if (summary.skippedUnchanged) {
|
|
stdout.writeln(
|
|
'[koi_swagger_parser] unchanged: skipped '
|
|
'${summary.generatedFiles.length} generated file(s); '
|
|
'${summary.operationsCount} operation(s), '
|
|
'${summary.modelsCount} model(s).',
|
|
);
|
|
} else {
|
|
stdout.writeln(
|
|
'[koi_swagger_parser] wrote ${summary.writtenFiles.length} file(s), '
|
|
'deleted ${summary.deletedFiles.length} stale file(s), '
|
|
'manages ${summary.generatedFiles.length} file(s); '
|
|
'${summary.operationsCount} operation(s), '
|
|
'${summary.modelsCount} model(s).',
|
|
);
|
|
}
|
|
} on Object catch (error, stackTrace) {
|
|
stderr.writeln('[koi_swagger_parser] Generation failed.');
|
|
if ((result['verbose'] as bool?) ?? false) {
|
|
stderr.writeln(error);
|
|
stderr.writeln(stackTrace);
|
|
} else {
|
|
stderr.writeln('Run with --verbose to see the underlying error.');
|
|
}
|
|
stderr.writeln();
|
|
stderr.writeln(_generateUsage(parser));
|
|
exitCode = 1;
|
|
}
|
|
}
|
|
|
|
String _usage(ArgParser parser) {
|
|
return [
|
|
'koi_swagger_parser',
|
|
'',
|
|
'Generate Retrofit and Freezed Dart sources from OpenAPI 3.0 or 3.1.',
|
|
'',
|
|
'Usage:',
|
|
' koi_swagger_parser <command> [arguments]',
|
|
' dart run koi_swagger_parser <command> [arguments]',
|
|
'',
|
|
'Global options:',
|
|
parser.usage,
|
|
'',
|
|
'Available commands:',
|
|
' generate Generate API clients and models.',
|
|
'',
|
|
'Run "koi_swagger_parser generate --help" for command options.',
|
|
].join('\n');
|
|
}
|
|
|
|
String _generateUsage(ArgParser parser) {
|
|
return [
|
|
'Generate API clients and models.',
|
|
'',
|
|
'Usage:',
|
|
' koi_swagger_parser generate [options]',
|
|
' dart run koi_swagger_parser generate [options]',
|
|
'',
|
|
'Options:',
|
|
parser.usage,
|
|
].join('\n');
|
|
}
|