Files
koi_swagger_parser/doc/zh-CN/ARCHITECTURE.md
T
mr.koi 454e6c51d7 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.
2026-07-31 16:47:39 +08:00

5.9 KiB
Raw Blame History

架构

English | 简体中文

生成流水线有意拆分为多个阶段:

配置
  -> 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。详见 配置参考。

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 留出空间。这些是设计方向,不是当前 公开版本的功能。当前实现边界见兼容性。

更多生态对比属于项目内部调研,不随发布 package 交付。