# 架构 [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`。 `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 交付。