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
+154
View File
@@ -0,0 +1,154 @@
# 架构
[English](../ARCHITECTURE.md) | [简体中文](ARCHITECTURE.md)
生成流水线有意拆分为多个阶段:
```text
配置
-> source loader
-> external/local $ref resolver
-> multi-source merger
-> validation + parser
-> transport/schema IR
-> preset + Dart renderer
-> manifest lifecycle
-> fix / format / build_runner
```
核心不变量是:加载阶段产生自包含且依赖可追踪的文档;parser 表达 OpenAPI
语义;renderer 不重新解释规范;lifecycle 只管理 manifest 中声明的文件。
## 配置
`lib/src/config/config.dart`:
- 查找 `koi_swagger_parser.yaml` 和兼容的 `generator_config.yaml` 名称;
- 相对 source/output 路径以配置文件目录解析;
- 从 `--cwd` 或显式配置目录确定宿主项目命令目录;
- 在转换 YAML scalar 前完成类型校验;
- 解析 enum、命名、type/import mapping 和 filter;
- 校验不支持的组合、mapping collision、正则和 enum mapping;
- 支持从旧 `base_result_import` 迁移。
未知 key 产生 warning;非法类型和不完整组合产生 error。详见
[配置参考](CONFIGURATION.md)。
## Loader、resolver 与 merger
对每个 root source,`OpenApiReferenceResolver`:
1. 规范化本地文件、file URL 或 HTTP(S) source;
2. 缓存每个加载的文档;
3. 解析 local、relative 和 remote `$ref`;
4. 把外部 component bundle 到根文档;
5. 为 component 冲突分配确定性名称;
6. 记录依赖并诊断无法支持的跨文档循环。
`OpenApiDocumentMerger` 再按配置顺序合并 root:
- 重复的 operation method/path 是 error;
- 同名但内容不同的 component 会确定性改名,并重写该 source 的 ref;
- 后输入不会静默覆盖冲突;
- 版本、info 和 path parameter 冲突会被报告。
parser 原则上只应收到根文档 JSON Pointer。仍然存在的 external ref 会被视为
resolver error。
## Validation 与 parser
`OpenApiDocumentParser` 负责:
- OpenAPI 3.0/3.1 版本和关键结构校验;
- operation、path、tag 和 model filter;
- parameter location、style、explode、`allowReserved` 和 `content`;
- request media type,以及 response status/content/header;
- server、security scheme 和 security requirement;
- required、nullable、readOnly/writeOnly 和 `additionalProperties` 语义;
- enum 配置/vendor extension 优先级;
- `allOf`、discriminator union 和已支持的 generic union;
- custom mapping 和 Dart 名称冲突。
无法用可靠 wire 语义渲染的结构不能静默退化为 `dynamic`。安全但有信息损失的
继续处理会产生 warning,例如不同成功 JSON body type 可能统一为 `Object?`。
XML、Protobuf 等没有已支持 decoder 的 media type 会产生 error。
## 中间表示
`lib/src/ir/ir.dart` 是 parser/renderer 契约,主要节点包括:
- `ApiOperation`:method、path、tag、version、server 和 security;
- `ApiParameter`:Dart/wire name、location、style、explode 和
`allowReserved`;
- `ApiRequestBody`:JSON、multipart、form-urlencoded 和 binary request;
- `ApiResponse`:status/default、body kind/type、content type 和 header;
- `ModelSpec`:object、enum、union model,以及 usage category 和 extras;
- `ModelField`:required/nullability/read-write flag 和 constraint;
- `DartType`:named、list、map、object、dynamic 和 void type graph。
model 按 request、result、shared、enum 分类。包含 readOnly/writeOnly 属性的
component 可投影为 request/response variant,避免 request 强制只读值,也避免
response 暴露 write-only secret。
generic `oneOf` 要求恰好一个 decoder 匹配。generic `anyOf` 保留 raw value 和
全部匹配 case。object 分支在 decode 前会用 required key 和 enum constraint
预筛。
## Preset 与 renderer
当前 `koi_flutter` preset 面向 Dio、Retrofit、Freezed 和 json_serializable。
renderer:
- 对 Retrofit 可表达的 parameter 形式使用 Retrofit annotation;
- 当已支持的 style、cookie 或 `allowReserved` 组合需要自定义序列化时,生成
typed public adapter 和 private Retrofit delegate;
- 渲染 Freezed object、enum 和 union model;
- 为根级 `properties` + `additionalProperties` 渲染自定义 map 读写 helper;
- 收集 model dependency 和 external type import;
- 按 version/tag 分组 API,并输出 client/index 文件。
renderer 不加载 ref,也不判断 OpenAPI 结构是否合法。
## 生成生命周期
落盘前,`GenerationLifecycle` 计算:
- canonical merged spec SHA-256;
- normalized config SHA-256;
- 每个渲染 path/content SHA-256。
manifest 记录 schema/generator version、source root、dependency 和每个主生成
文件的实际 hash。写入使用操作系统 exclusive lock 和同目录临时文件 rename。
安全不变量:
1. renderer 输出必须位于配置的 API/model 根;
2. stale candidate 必须来自旧 manifest;
3. stale path 仍必须位于当前 managed root;
4. 删除前当前 hash 必须等于旧 manifest hash;
5. 损坏或未知版本 manifest 不参与删除;
6. fix/format/build 失败时不写 success manifest;
7. watch 在释放生成锁后启动。
`.g.dart` 和 `.freezed.dart` 由 build_runner 管理,不进入本生成器的 stale
manifest。
## Response wrapper
parser 不硬编码 `BaseResult`:
- `passthrough` 返回 OpenAPI response schema;
- `external_generic` 检测配置的成功 envelope,并返回
`ExternalWrapper<Inner>`。
`default` response 仍是错误响应。`response_mode: http_response` 保留 Dio
status/header。错误 response model 仍保留在 IR 和生成 model 集合中。
## 扩展边界
IR/preset/renderer 分层为未来的版本化 renderer interface、template override、
semantic diff 和可选 runtime adapter 留出空间。这些是设计方向,不是当前
公开版本的功能。当前实现边界见[兼容性](COMPATIBILITY.md)。
更多生态对比属于项目内部调研,不随发布 package 交付。