Establish the Koi Swagger parser release

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.
This commit is contained in:
mr.koi
2026-06-02 22:00:13 +08:00
commit ea93f09154
24 changed files with 11355 additions and 0 deletions
+114
View File
@@ -0,0 +1,114 @@
# Architecture
`koi_swagger_parser` 采用“加载 -> 解析 -> IR -> 渲染 -> 落盘”的分层设计,避免把 OpenAPI 细节、Koi 业务约定、具体 Dart 输出模板揉在一起。
## 1. 分层
### config
负责读取与归一化配置:
- 新配置:`koi_swagger_parser.yaml`
- 兼容配置:`generator_config.yaml`
- 路径归一化、默认值、旧字段兼容映射
- preset 解析(当前内置 `koi_flutter`)
### openapi
负责:
- 本地/远程文档加载
- 多 source 深合并
- schema/ref 解析
- OpenAPI 3.1 nullable / anyOf / oneOf / additionalProperties / allOf 归一化
- multipart request body 与 discriminator union 识别
### ir
产出与 OpenAPI 原文解耦的中间表示:
- API operation
- request body / parameter
- model / enum
- Dart type graph
IR 是后续接入 `koi_blueprint_flutter` preset 的关键。
### generator
只关心如何把 IR 渲染成 Dart 文件:
- Retrofit API
- Freezed model
- enums
- index/client 聚合文件
这一层不直接处理 OpenAPI 细节。
### preset
用于把 parser core 的 IR 和具体客户端技术栈解耦。当前先提供一个很薄的 preset 层:
- `koi_flutter`:默认面向 Retrofit + Dio + Freezed
- 当前主要控制 multipart 二进制字段该生成为 `MultipartFile`、`File`、`Uint8List` 还是 `String`
- 后续可以继续扩展 blueprint preset、网络层 preset、命名/包装策略 preset
## 2. Response Wrapper 设计
parser core 不直接写死 `BaseResult`。
当前支持两种模式:
- `passthrough`
- 返回真实 OpenAPI response schema
- 适合你希望保留服务端 envelope 模型的场景
- `external_generic`
- 识别标准成功 envelope(默认 `code/message/data`)
- 将 `data` 提取为 inner type
- API 返回 `ExternalWrapper<Inner>`,例如 `BaseResult<KoiStoreResponse>`
这样做的意义是:
- parser core 保持通用
- Koi 网络层包裹策略可配置
- 未来可以挂更多 wrapper preset,而不是继续堆服务端补丁
## 3. 模型分组
模型按使用语义归档:
- `request/`:只在请求体根节点使用
- `result/`:只在成功响应根节点使用
- `shared/`:被请求与响应共同依赖,或用于错误响应
- `enums/`:枚举单独分组
这比“按 swagger component 平铺”更符合 Koi 项目结构,也更利于未来蓝图模板整理。
## 4. 命名原则
- 类名统一 PascalCase。
- 字段统一 camelCase,并保留 `@JsonKey(name: ...)` 对应 wire name。
- 文件名统一 snake_case。
- API 默认按 `version + tag` 分文件。
命名转换统一收口到 util 层,避免每个阶段各写一套字符串处理逻辑。
## 5. 为什么新建项目而不是继续修补旧生成器
旧生成器的问题不是单点 bug,而是结构性耦合:
- OpenAPI 解析和业务输出绑定太深。
- nullable / anyOf / wrapper 规则分散在多个模板与解析阶段。
- 很难为未来 `koi_blueprint_flutter` 抽出复用 IR。
所以这里直接重新收口:
- parser core 面向 OpenAPI 语义
- Koi 输出作为 renderer/preset
- 兼容旧配置,但不延续旧架构负担
## 6. 近期路线
- 第一阶段:打通 Koi/FastAPI 场景(已完成)
- 第二阶段:补齐 multipart、discriminator union、preset 基础层(当前版本)
- 第三阶段:扩更强 union fallback、更多 preset,并服务 `koi_blueprint_flutter`