Release 0.2.0

Complete OpenAPI 3.0/3.1 generation, diagnostics, lifecycle safety, enum and naming mappings, bilingual documentation, examples, and pub.dev release validation.
This commit is contained in:
mr.koi
2026-07-31 16:47:39 +08:00
parent ea93f09154
commit 454e6c51d7
56 changed files with 14506 additions and 491 deletions
+316 -81
View File
@@ -1,26 +1,95 @@
# koi_swagger_parser
`koi_swagger_parser` 是一个面向 Koi 生态的新一代 OpenAPI 解析与 Dart 代码生成器,目标不是继续修补旧式 Swagger 生成链,而是为未来的 `koi_blueprint_flutter` 提供一套更稳、更清晰、更可扩展的基础设施。
[English](README.md) | [Chinese (Simplified)](README.zh-CN.md)
当前版本聚焦 Koi/FastAPI 场景,优先解决这几类问题:
`koi_swagger_parser` is an OpenAPI 3.0/3.1 Dart and Flutter client generator
for projects that use Dio, Retrofit, Freezed, and json_serializable. It
separates document loading, `$ref` resolution, validation, an intermediate
representation (IR), rendering, and safe incremental writes.
- OpenAPI 3.1 下 `anyOf[T, null]`、`type: [T, null]` 的 nullable 解析。
- FastAPI `code/message/data` 成功 envelope 的识别与外部泛型包装。
- `multipart/form-data` 请求体生成 `@MultiPart()` + `@Part()`,并按 preset 选择二进制类型。
- `oneOf` / `anyOf` + discriminator 生成 sealed union wrapper。
- 以 Koi 目录结构输出 `api/`、`api_models/request|result|shared|enums/`。
- 兼容旧版 `generator_config.yaml`,平滑替换 `swagger_generator_flutter`。
Generated code follows a Koi-oriented layout:
## 设计目标
```text
lib/src/
api/
api_client.dart
index.dart
v1/
index.dart
stores_api.dart
api_models/
api_models.dart
request/
result/
shared/
enums/
```
- 解析层和 Koi 业务约束解耦:parser core 不硬编码 `BaseResult`。
- 先产出中间表示(IR),再做 Koi 风格渲染,方便未来扩展到 `koi_blueprint_flutter`。
- 默认以 Retrofit + Freezed 为输出基线,但 response wrapper 可配置。
- 对 FastAPI/SQLAlchemy 风格服务端有良好适配,同时不把服务端补丁写死在生成器里。
## Features
## 配置文件
- Local JSON/YAML files, HTTP(S) documents, multiple root documents, and
local, relative, file, and remote `$ref` values.
- Component reference resolution, caching, cycle detection, deterministic
conflict handling, and dependency tracking.
- Retrofit APIs and Freezed/json_serializable request, response, shared,
enum, and union models.
- `enum_mappings`, legacy `enum_key_mappings`, `x-enumNames`,
`x-enum-varnames`, `x-enum-values`, descriptions, and optional unknown enum
fallback.
- Model, property, parameter, operation, schema, type, and import mappings
with collision diagnostics.
- OpenAPI path, query, header, and cookie parameters, including supported
style, explode, and `allowReserved` combinations.
- JSON, text, multipart, form-urlencoded, and binary requests; byte and
stream downloads.
- Multiple successful responses, 204, `2XX`, `default` and error responses,
response headers, and optional `HttpResponse<T>` results.
- Required, nullable, and absent-value semantics; read-only/write-only
projections; `additionalProperties`; `allOf`; and supported `oneOf`/`anyOf`
forms.
- Server variables and security metadata. Credentials remain the
responsibility of the host application's Dio interceptor or provider.
- Exact, glob, and regular-expression filters.
- A locked manifest, SHA-256 change detection, safe stale-file cleanup,
atomic writes, dry runs, and optional build_runner integration.
推荐使用 `koi_swagger_parser.yaml`:
See the [compatibility matrix](doc/COMPATIBILITY.md) for precise boundaries.
## Requirements
- Dart SDK `^3.11.0`.
- An OpenAPI 3.0.x or 3.1.x document in JSON or YAML.
- A host Dart or Flutter project configured for Retrofit, Freezed, and
json_serializable when generating both APIs and models.
## Installation
Add the generator as a development dependency in the host project:
```bash
dart pub add --dev koi_swagger_parser
```
For a typical generated client, add these host runtime dependencies:
```bash
dart pub add dio retrofit freezed_annotation json_annotation
```
Add the matching code-generation tools:
```bash
dart pub add --dev build_runner retrofit_generator freezed json_serializable
```
For Flutter projects, use `flutter pub add` in place of `dart pub add` if that
is how the project manages dependencies.
## Quick start
1. Copy [the complete configuration template](koi_swagger_parser.example.yaml)
to `koi_swagger_parser.yaml` in the host project.
2. Set at least one OpenAPI source and the output directories:
```yaml
input:
@@ -32,12 +101,6 @@ output:
base_dir: ./lib/src
api_dir: ./lib/src/api
models_dir: ./lib/src/api_models
included_tags:
- auth
- stores
- materials
split_by_tags: true
extract_version_from_url: false
generation:
preset:
@@ -45,93 +108,265 @@ generation:
api:
enabled: true
use_retrofit: true
cancel_token_support: true
client:
class_name: DbaApiClient
file_name: dba_api_client
response_wrapper:
mode: external_generic
success_data_field: data
detect_standard_envelope: true
external_generic:
import: package:dba_network/dba_network.dart
class_name: BaseResult
mode: passthrough
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: true
run_build_runner: true
build_runner_mode: build
```
也兼容旧版 `generator_config.yaml`:
3. Preview the change set:
- `generation.api.base_result_import` 会自动映射为 `response_wrapper.mode = external_generic`。
- `output.included_tags`、`generation.models.class_prefix` 等旧字段会继续生效。
```bash
dart run koi_swagger_parser generate --all --dry-run
```
## 命令行
4. Generate the client:
```bash
dart run koi_swagger_parser generate --all
```
常用参数:
When `formatting.run_build_runner` is `false`, run build_runner separately:
- `--config`:指定配置文件路径。
- `--cwd`:指定工作目录。
- `--dry-run`:只解析与渲染,不落盘。
- `--verbose`:打印更多诊断信息。
## 输出结构
默认会生成:
```text
lib/src/
api/
dba_api_client.dart
index.dart
v1/
index.dart
auth_api.dart
stores_api.dart
api_models/
api_models.dart
request/
result/
shared/
enums/
```bash
dart run build_runner build --delete-conflicting-outputs
```
## 当前能力
## CLI usage
当前版本已经覆盖 Koi 当前最需要的能力:
```text
dart run koi_swagger_parser generate [options]
- OpenAPI 3.1 文档加载(本地 JSON/YAML、远程 URL、多 source merge)。
- `object` / `array` / `enum` / `additionalProperties` / `allOf` 基础支持。
- nullable query/path/body 字段解析。
- FastAPI envelope 检测与 `BaseResult<T>` 外部包装。
- `multipart/form-data` 生成 `MultipartFile` / `File` / `Uint8List` / `String` 等 preset 驱动参数。
- `oneOf` / `anyOf` + discriminator 生成 sealed union wrapper,并可被其他模型继续引用。
- Retrofit API 文件、Freezed 模型文件、分组 index 文件生成。
--all, -a Generate all enabled resources. Kept for command compatibility.
--config, -c Configuration file path.
--cwd Host project working directory.
--dry-run Parse and render without writing or deleting files.
--watch Start build_runner watch after generation.
--verbose, -v Print informational diagnostics and failure stack traces.
```
下一阶段可以继续往前加:
The loader searches the working directory for, in order:
- 更丰富的 multipart metadata(如 encoding / runtime fileName / contentType preset)。
- 无 discriminator 的更强联合类型兜底策略。
- 更多 preset(例如 Chopper / blueprint preset / 网络层集成 preset)。
- 与 `koi_blueprint_flutter` 的一键联动模板。
1. `koi_swagger_parser.yaml`
2. `koi_swagger_parser.yml`
3. `generator_config.yaml`
4. `generator_config.yml`
## 开发与验证
When `--config` points to a file outside the current directory and `--cwd` is
not set, the configuration directory becomes the host project working
directory. Relative sources and output paths are resolved against the
configuration directory. `--cwd` changes where host-project commands run; it
does not change those path semantics.
## Library usage
The same pipeline is available as a Dart API:
```dart
import 'package:koi_swagger_parser/koi_swagger_parser.dart';
Future<void> main() async {
final result = await const KoiSwaggerParser().generate(
configPath: 'koi_swagger_parser.yaml',
dryRun: true,
);
print('${result.operationsCount} operations');
print('${result.modelsCount} models');
for (final diagnostic in result.diagnostics) {
print(diagnostic.format());
}
}
```
On diagnostic errors, generation throws `KoiDiagnosticException`. Automation
should match diagnostic `code` values instead of message text. See
[Diagnostics](doc/DIAGNOSTICS.md).
## Enum mappings
Enum wire values can be mapped to stable Dart member names in configuration:
```yaml
generation:
models:
enum_unknown_fallback: true
enum_mappings:
OrderStatus:
- value: pending
name: waitingForPayment
description: Waiting for payment
- value: done
name: completed
description: Completed
```
Map syntax is also accepted:
```yaml
generation:
models:
enum_mappings:
OrderStatus:
pending: waitingForPayment
done:
name: completed
description: Completed
```
The legacy `enum_key_mappings` field remains supported. Name resolution uses
this precedence:
1. `enum_mappings`
2. `enum_key_mappings`
3. `x-enumNames`, `x-enum-names`, or `x-enum-varnames`
4. `x-enum-values`
5. A name derived from the wire value
Descriptions use configuration first, then `x-enumDescriptions`,
`x-enum-descriptions`, and `x-enum-values.description`. With
`enum_unknown_fallback: true`, the generator adds a stable `unknown` member
and applies `JsonKey.unknownEnumValue` to enum references.
## Naming and type mappings
```yaml
generation:
mappings:
models:
UserDto: User
properties:
UserDto:
user_id: id
parameters:
getUser:
user_id: id
operations:
getUser: fetchUser
"DELETE /api/v1/users/{id}": removeUser
schemas:
Money:
type: Money
import: package:money2/money2.dart
types:
string:uuid:
type: UuidValue
import: package:uuid/uuid_value.dart
integer:int64: int
imports:
UuidValue: package:uuid/uuid_value.dart
```
Operation mapping keys accept either an `operationId` or `METHOD /path`.
Schema mappings mark a schema as externally implemented, so no model is
generated for it. The external type must provide the JSON conversion behavior
required by its generated usage.
## Responses and transport
```yaml
generation:
api:
cancel_token_support: true
response_mode: http_response # body | http_response
binary_response_mode: bytes # bytes | stream
client:
class_name: ApiClient
file_name: api_client
response_wrapper:
mode: external_generic # passthrough | external_generic
success_data_field: data
detect_standard_envelope: true
external_generic:
import: package:your_network/your_network.dart
class_name: BaseResult
```
When Retrofit annotations cannot represent a supported matrix, label, cookie,
deep-object, or reserved-character parameter, the generator emits a typed
transport adapter in front of a private Retrofit delegate. A `default`
response is always treated as an error response.
## Filtering and lifecycle
```yaml
output:
included_tags: [stores]
excluded_paths: [/internal/**]
included_operations: [getStore, "POST /api/v1/stores"]
excluded_models: [Legacy*]
clean_stale_files: true
skip_if_unchanged: true
manifest_path: ./.dart_tool/koi_swagger_parser/manifest.json
```
Filters accept exact values, `*`, `?`, and `**` globs, or Dart regular
expressions prefixed with `regex:`. Exclusions take precedence over
inclusions. `included_models` can add otherwise unreferenced components as
generation roots.
The manifest records only files owned by this generator. Stale cleanup removes
an old generated file only when it is still inside the configured API/model
roots and its content still matches the previous manifest hash. Modified files
and handwritten neighbors are preserved.
## Limitations
The current release intentionally does not generate:
- Swagger/OpenAPI 2.0 clients.
- Callbacks, webhooks, or Link Object call chains.
- XML, Protobuf, or arbitrary custom codecs.
- A complete JSON Schema 2020-12 implementation.
- Server stubs, mock servers, or non-Dart targets.
- A pluggable external renderer/template API.
Unsupported or lossy constructs produce structured warnings or errors; they
are not silently presented as fully supported. Consult
[Compatibility](doc/COMPATIBILITY.md) before adopting the generator for a new
schema corpus.
## Documentation
- [Configuration reference](doc/CONFIGURATION.md)
- [Compatibility matrix](doc/COMPATIBILITY.md)
- [Diagnostics reference](doc/DIAGNOSTICS.md)
- [Architecture](doc/ARCHITECTURE.md)
- [Migration from swagger_generator_flutter](doc/MIGRATION.md)
- [Changelog](CHANGELOG.md)
## Development
```bash
dart pub get
dart format .
dart analyze
dart test
dart run tool/verify_generated_package.dart
```
架构设计说明见 `doc/ARCHITECTURE.md`。
The final command creates a temporary Dart package, invokes this generator and
its build_runner integration, and then runs analysis and runtime tests in the
generated package.
## Support and contributing
Use [GitHub Issues](https://github.com/mrkoi-is/koi_swagger_parser/issues) for
reproducible bug reports and feature requests. Include the generator version,
Dart version, a minimal OpenAPI document, the relevant configuration, and
diagnostic codes. Remove credentials and private service data before sharing a
reproduction.
Contributions should include focused tests and update the compatibility matrix
and configuration reference when behavior changes. Run the development checks
above before opening a pull request.
## License
[MIT](LICENSE)