Prepare the OpenAPI parser and Dart generator as a publishable Koi package with CLI entrypoint, docs, examples, tests, and pub.dev release metadata. Constraint: Initial GitHub import follows koi_blueprint_flutter identity mr.koi <i@mrkoi.is>. Rejected: Keep local runtime state in the initial repository | .dart_tool, .omx, and pubspec.lock are ignored for a reusable package source tree. Confidence: high Scope-risk: moderate Directive: Keep generated-output behavior covered by parser and generator tests before changing rendering rules. Tested: dart analyze; dart test; PUB_HOSTED_URL=https://pub.dev dart pub publish --dry-run Not-tested: End-to-end downstream build_runner compilation of generated Retrofit/Freezed output.
140 lines
3.5 KiB
Dart
140 lines
3.5 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:koi_swagger_parser/koi_swagger_parser.dart';
|
|
import 'package:path/path.dart' as p;
|
|
import 'package:test/test.dart';
|
|
|
|
void main() {
|
|
group('passthrough wrapper', () {
|
|
test('保留 envelope 模型并生成 enum', () async {
|
|
final tempDir = await Directory.systemTemp.createTemp(
|
|
'koi_swagger_parser_passthrough_',
|
|
);
|
|
addTearDown(() => tempDir.delete(recursive: true));
|
|
|
|
final specFile = File(p.join(tempDir.path, 'openapi.json'));
|
|
await specFile.writeAsString('''
|
|
{
|
|
"openapi": "3.1.0",
|
|
"info": {
|
|
"title": "Sample",
|
|
"version": "1.0.0"
|
|
},
|
|
"paths": {
|
|
"/api/v1/orders": {
|
|
"get": {
|
|
"tags": ["orders"],
|
|
"operationId": "list_orders_api_v1_orders_get",
|
|
"responses": {
|
|
"200": {
|
|
"description": "ok",
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"\$ref": "#/components/schemas/ApiResponse_OrderStatusResponse_"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"schemas": {
|
|
"ApiResponse_OrderStatusResponse_": {
|
|
"type": "object",
|
|
"required": ["data"],
|
|
"properties": {
|
|
"code": {"type": "integer"},
|
|
"message": {"type": "string"},
|
|
"data": {"\$ref": "#/components/schemas/OrderStatusResponse"}
|
|
}
|
|
},
|
|
"OrderStatusResponse": {
|
|
"type": "object",
|
|
"required": ["status"],
|
|
"properties": {
|
|
"status": {"\$ref": "#/components/schemas/OrderStatus"}
|
|
}
|
|
},
|
|
"OrderStatus": {
|
|
"type": "string",
|
|
"enum": ["pending", "done"]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
''');
|
|
|
|
final outputDir = p.join(tempDir.path, 'lib', 'src');
|
|
final configFile = File(p.join(tempDir.path, 'koi_swagger_parser.yaml'));
|
|
await configFile.writeAsString('''
|
|
input:
|
|
swagger_urls:
|
|
- url: ${specFile.path}
|
|
enabled: true
|
|
|
|
output:
|
|
base_dir: $outputDir
|
|
api_dir: ${p.join(outputDir, 'api')}
|
|
models_dir: ${p.join(outputDir, 'api_models')}
|
|
split_by_tags: true
|
|
|
|
generation:
|
|
api:
|
|
enabled: true
|
|
use_retrofit: true
|
|
cancel_token_support: false
|
|
client:
|
|
class_name: SampleApiClient
|
|
file_name: sample_api_client
|
|
response_wrapper:
|
|
mode: passthrough
|
|
detect_standard_envelope: true
|
|
success_data_field: data
|
|
models:
|
|
enabled: true
|
|
class_prefix: Koi
|
|
default_non_nullable_list_to_empty: true
|
|
json_serializable:
|
|
checked: true
|
|
explicit_to_json: true
|
|
include_if_null: false
|
|
formatting:
|
|
run_dart_format: false
|
|
''');
|
|
|
|
await const KoiSwaggerParser().generate(configPath: configFile.path);
|
|
|
|
final apiFile = File(
|
|
p.join(outputDir, 'api', 'v1', 'orders_api.dart'),
|
|
).readAsStringSync();
|
|
expect(
|
|
apiFile,
|
|
contains('Future<KoiApiResponseOrderStatusResponse> listOrders'),
|
|
);
|
|
expect(apiFile, isNot(contains('BaseResult')));
|
|
|
|
final envelopeModel = File(
|
|
p.join(
|
|
outputDir,
|
|
'api_models',
|
|
'result',
|
|
'api_response_order_status_response.dart',
|
|
),
|
|
).readAsStringSync();
|
|
expect(
|
|
envelopeModel,
|
|
contains('class KoiApiResponseOrderStatusResponse'),
|
|
);
|
|
|
|
final enumFile = File(
|
|
p.join(outputDir, 'api_models', 'enums', 'order_status.dart'),
|
|
).readAsStringSync();
|
|
expect(enumFile, contains('enum KoiOrderStatus'));
|
|
expect(enumFile, contains("@JsonValue('pending')"));
|
|
});
|
|
});
|
|
}
|