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:
@@ -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 交付。
|
||||
@@ -0,0 +1,67 @@
|
||||
# 更新日志
|
||||
|
||||
本文件记录此 package 的重要变更。
|
||||
|
||||
[English](../../CHANGELOG.md) | [简体中文](CHANGELOG.md)
|
||||
|
||||
## 0.2.0 - 2026-07-31
|
||||
|
||||
### 破坏性变更
|
||||
|
||||
- 主 library 不再导出 `DartType`、`ModelSpec`、`ApiOperation`、
|
||||
`GeneratedFile`、`GeneratedBundle` 等 parser IR 实现类型;请改用
|
||||
`KoiSwaggerParser` 及其文档化的 `GenerationResult`;
|
||||
- 不再导出 `KoiSwaggerConfigLoader`;程序化加载配置请改用
|
||||
`KoiSwaggerConfig.load()`。
|
||||
|
||||
### 新增
|
||||
|
||||
- 结构化配置、OpenAPI、过滤和生命周期诊断;error 不再静默生成已知错误代码;
|
||||
- local、relative、file 和 HTTP(S) `$ref` 解析,包括缓存、循环检测、依赖
|
||||
追踪、外部 component bundling 和确定性多 source 冲突处理;
|
||||
- `enum_mappings`、兼容字段 `enum_key_mappings`、常见 `x-enum` 扩展、描述和
|
||||
可选 unknown enum fallback;
|
||||
- model、property、parameter、operation、schema、type 和 import 映射及冲突校验;
|
||||
- OpenAPI path、query、header、cookie 参数序列化,包括已支持的 matrix、label、
|
||||
form、simple、spaceDelimited、pipeDelimited、deepObject、explode 和
|
||||
`allowReserved` 组合;
|
||||
- JSON、text、multipart、form-urlencoded 和 binary upload,以及 bytes/stream
|
||||
download;
|
||||
- 多成功响应、204、`2XX`、`default`、错误模型、响应头和 `HttpResponse<T>` 模式;
|
||||
- required、nullable、absent 语义、readOnly/writeOnly 投影,以及根级
|
||||
`properties` + `additionalProperties` round trip;
|
||||
- `allOf`、discriminator union,以及已支持的 primitive、container、object
|
||||
`oneOf`/`anyOf`;
|
||||
- server variables、security schemes 和 operation OR/AND security metadata;
|
||||
- tag、path、operation、model 的精确、glob 和正则过滤;
|
||||
- 带锁 manifest、spec/config/content SHA-256、未变化跳过、安全 stale cleanup、
|
||||
原子写入和 dry-run 变更计划;
|
||||
- 内置 build_runner build/watch 集成、reviewed golden、OpenAPI 3.0/3.1 fixture
|
||||
和临时生成包验证;
|
||||
- 英文 canonical 文档与完整简体中文镜像,以及配置、兼容性、诊断和迁移参考。
|
||||
|
||||
### 变更
|
||||
|
||||
- `GenerationResult.writtenFiles` 现在只包含实际写入文件;`generatedFiles` 包含
|
||||
完整目标集合;dry-run 使用 `wouldWriteFiles` 和 `wouldDeleteFiles`;
|
||||
- 显式传入配置文件且未设置 `workingDirectory`/`--cwd` 时,配置文件目录成为
|
||||
宿主项目工作目录;
|
||||
- `default` response 不再视为成功;XML、Protobuf 和没有安全 decoder 的其他
|
||||
response media type 会产生诊断;
|
||||
- `dart fix` 和 `dart format` 仅处理本轮改变的主生成文件。
|
||||
- 所有非测试 Dart 声明均在不使用文件级排除的情况下满足
|
||||
`public_member_api_docs`,包括内部 IR 和 lifecycle 类型。
|
||||
|
||||
### 修复
|
||||
|
||||
- 使 `formatting.run_dart_fix` 和 `output.extract_version_from_url` 真正生效;
|
||||
- 避免 Dio/Retrofit `Headers` import 冲突、Freezed custom `toJson` 缺失,以及
|
||||
parameter、field、method mapping 碰撞。
|
||||
- lifecycle manifest 记录的生成器版本已与 package `0.2.0` 同步。
|
||||
|
||||
## 0.1.0 - 2026-06-02
|
||||
|
||||
- 首次发布 `koi_swagger_parser`;
|
||||
- 支持常见 OpenAPI 3.1/FastAPI 解析、Koi 风格 Retrofit API 生成和 Freezed
|
||||
模型生成;
|
||||
- 支持兼容读取旧版 `generator_config.yaml`。
|
||||
@@ -0,0 +1,113 @@
|
||||
# 兼容性
|
||||
|
||||
[English](../COMPATIBILITY.md) | [简体中文](COMPATIBILITY.md)
|
||||
|
||||
本矩阵只描述当前实现和自动化测试已覆盖的行为。
|
||||
|
||||
- **支持**:已经实现并测试;
|
||||
- **部分支持**:仅支持“边界”列出的子集;
|
||||
- **不支持**:生成前产生诊断,或 warning 后明确忽略。
|
||||
|
||||
## 文档、引用与合并
|
||||
|
||||
| 能力 | 状态 | 边界 |
|
||||
|---|---|---|
|
||||
| OpenAPI 3.0.x / 3.1.x | 支持 | JSON/YAML;客户端生成所需常见 Schema Object 子集 |
|
||||
| Swagger/OpenAPI 2.0 | 不支持 | `openapi.unsupported_version` error |
|
||||
| 本地 `$ref` | 支持 | 各 component 分组的 JSON Pointer |
|
||||
| 相对文件 / file URL `$ref` | 支持 | 相对当前引用文档解析 |
|
||||
| HTTP(S) `$ref` | 支持 | 单次运行缓存、依赖追踪和循环诊断 |
|
||||
| 外部 component 重名 | 支持 | 确定性改名并 warning |
|
||||
| 多 root source | 支持 | 确定性 merge;component/operation 冲突诊断 |
|
||||
| unresolved `$ref` | 支持诊断 | error,不静默转换成 `dynamic` |
|
||||
| callbacks / webhooks | 不支持 | warning,不生成反向调用 client |
|
||||
| Link Object | 不支持 | `openapi.links_not_supported` warning |
|
||||
|
||||
当前不是完整 JSON Schema 2020-12 实现。`$defs` 作为生成根、
|
||||
`if`/`then`/`else`、`not`、`contains`、`dependentSchemas` 和 unevaluated
|
||||
property/item 语义不在当前契约中。
|
||||
|
||||
## Schema 与 model
|
||||
|
||||
| 能力 | 状态 | 边界 |
|
||||
|---|---|---|
|
||||
| object / array / map | 支持 | 递归容器和 inline schema |
|
||||
| `properties` + `additionalProperties` | 支持 | extra entry 在 JSON 根 round trip |
|
||||
| string/number/integer/bool/date/date-time | 支持 | format 可由 type mapping 覆盖 |
|
||||
| enum | 支持 | string、number、boolean wire value;inline/component |
|
||||
| enum 成员名映射 | 支持 | 配置及常见 `x-enum` extension |
|
||||
| enum unknown fallback | 支持 | 可配置 `JsonKey.unknownEnumValue` 输出 |
|
||||
| required / nullable / absent | 支持 | 反序列化区分缺失和不允许 null;普通 Freezed 字段不保留 presence 历史 |
|
||||
| readOnly / writeOnly | 支持 | 必要时生成 request/response directional variant |
|
||||
| `allOf` | 支持 | 合并 object property、required 和 additional property |
|
||||
| discriminator `oneOf`/`anyOf` | 支持 | local 或已归一化 object branch |
|
||||
| 无 discriminator `oneOf`/`anyOf` | 部分支持 | primitive/container/object;重叠 `oneOf` 匹配会拒绝 |
|
||||
| custom schema/type/format | 支持 | external import;宿主代码负责 JSON 转换契约 |
|
||||
| constraint metadata | 部分支持 | 保留 description/doc comment;不生成 runtime validator |
|
||||
| presence/dirty tracking | 不支持 | 无 Kiota 风格 backing store |
|
||||
|
||||
## HTTP wire 语义
|
||||
|
||||
| 能力 | 状态 | 边界 |
|
||||
|---|---|---|
|
||||
| path/query/header/cookie parameter | 支持 | type、required/default 和 wire name |
|
||||
| matrix / label / simple | 支持 | 校验 location/style 组合 |
|
||||
| form / spaceDelimited / pipeDelimited / deepObject | 支持 | 校验 query/cookie 组合 |
|
||||
| explode / `allowReserved` | 支持 | Retrofit 无法表达时生成 transport adapter |
|
||||
| Parameter Object `content` | 部分支持 | 必须恰有一个 media type |
|
||||
| JSON / `+json` request body | 支持 | required body 和 null-to-absent |
|
||||
| text request body | 支持 | typed `@Body` |
|
||||
| `multipart/form-data` | 支持 | binary、primitive、array 和 structured JSON part |
|
||||
| `application/x-www-form-urlencoded` | 支持 | typed field;复杂 encoding 使用 adapter |
|
||||
| binary upload | 支持 | `Uint8List` |
|
||||
| binary download | 支持 | `Uint8List` 或 Dio `ResponseBody` stream |
|
||||
| XML / Protobuf / 任意 custom codec | 不支持 | content-type error,不生成不安全 decoder |
|
||||
|
||||
## Response、server 与 security
|
||||
|
||||
| 能力 | 状态 | 边界 |
|
||||
|---|---|---|
|
||||
| 多个 2xx / 204 / `2XX` | 支持 | 确定性 primary response;不同 JSON type 可 warning 后变成 `Object?` |
|
||||
| `default` / 4xx / 5xx | 支持 | 保留 error model/IR metadata;不作为 success |
|
||||
| response header | 支持 | status、type、required flag 和 description |
|
||||
| raw response metadata | 支持 | `response_mode: http_response` |
|
||||
| binary + JSON 混合 success media | 支持诊断 | 单个 Retrofit 方法无法安全 decode 时 error |
|
||||
| root/path/operation server | 支持 | server variable default/enum 校验;preferred server 成为 client default |
|
||||
| 多 server runtime 切换 | 部分支持 | 保留 metadata;不生成环境选择 UI |
|
||||
| API key / Bearer / Basic | 支持 metadata | 生成 scheme/operation requirement;凭证由宿主 interceptor/provider 提供 |
|
||||
| OAuth2 / OpenID / mutual TLS | 部分支持 | 仅 scheme/scope metadata;不生成完整授权流程 |
|
||||
| security OR/AND requirement | 支持 | list 项是 OR;同一 map 项中的 scheme 是 AND |
|
||||
|
||||
## 生成与生命周期
|
||||
|
||||
| 能力 | 状态 | 边界 |
|
||||
|---|---|---|
|
||||
| Retrofit + Freezed | 支持 | 当前版本唯一完整 renderer |
|
||||
| passthrough / external generic wrapper | 支持 | 可配置标准 envelope 检测 |
|
||||
| model/property/parameter/operation mapping | 支持 | collision 校验和安全 identifier |
|
||||
| schema/type/import mapping | 支持 | 递归 Dart `List`/`Map` type expression |
|
||||
| tag/path/operation/model filter | 支持 | exact、glob 和 `regex:` |
|
||||
| dry-run | 支持 | 报告 would-write/would-delete |
|
||||
| Dart fix / format | 支持 | 仅本轮改变的主生成文件 |
|
||||
| build_runner build/watch | 支持 | 在配置的宿主项目目录执行 |
|
||||
| unchanged skip | 支持 | spec/config/content 和实际文件 SHA-256 |
|
||||
| stale cleanup | 支持 | manifest ownership、root containment、用户修改保护 |
|
||||
| concurrent generation lock | 支持 | manifest 旁的操作系统 exclusive lock |
|
||||
| external template / plugin renderer | 不支持 | IR/preset 已分层,但无公开 renderer SPI |
|
||||
| 完整 SDK package scaffold | 不支持 | 在已有项目内生成 API/model |
|
||||
|
||||
## 验证覆盖
|
||||
|
||||
仓库测试覆盖:
|
||||
|
||||
- parser、IR、renderer 和 lifecycle 阶段;
|
||||
- OpenAPI 3.0 YAML、OpenAPI 3.1 JSON/FastAPI fixture;
|
||||
- enum/命名 mapping、parameter wire style、response、schema 语义、security
|
||||
和 external/cyclic ref;
|
||||
- reviewed SHA-256 golden;
|
||||
- 生成到临时 Dart package,随后运行 build_runner、analysis 和 runtime test。
|
||||
|
||||
矩阵中的“支持”不代表超出所列边界的完整 OpenAPI/JSON Schema conformance。
|
||||
引入新的 schema corpus 时,应先用最小 fixture 和 dry-run 验证。
|
||||
|
||||
诊断含义和处理方式见[诊断参考](DIAGNOSTICS.md)。
|
||||
@@ -0,0 +1,254 @@
|
||||
# 配置参考
|
||||
|
||||
[English](../CONFIGURATION.md) | [简体中文](CONFIGURATION.md)
|
||||
|
||||
`koi_swagger_parser` 使用 YAML 配置。完整注释示例见
|
||||
[koi_swagger_parser.example.yaml](../../koi_swagger_parser.example.yaml)。
|
||||
未知字段会产生 `config.unknown_key`;非法 scalar 类型和非法组合会在 OpenAPI
|
||||
解析前报错。
|
||||
|
||||
## 查找顺序与路径语义
|
||||
|
||||
未传入 `--config` 时,加载器按以下顺序在工作目录查找:
|
||||
|
||||
1. `koi_swagger_parser.yaml`
|
||||
2. `koi_swagger_parser.yml`
|
||||
3. `generator_config.yaml`
|
||||
4. `generator_config.yml`
|
||||
|
||||
所有相对 OpenAPI 文件 source、输出目录和显式 manifest 路径都以所选配置文件的
|
||||
目录为基准。未找到配置文件时,以命令调用目录为基准。
|
||||
|
||||
显式传入配置文件且未指定 `--cwd` 时,其目录也会成为 build_runner 使用的宿主
|
||||
项目工作目录。`--cwd` 可覆盖命令工作目录,但不会重新解释配置中的相对路径。
|
||||
HTTP(S) source URL 保持 URL 语义。
|
||||
|
||||
## 顶层字段
|
||||
|
||||
| 字段 | 类型 | 必填 | 默认值 |
|
||||
|---|---|---:|---|
|
||||
| `input` | map | 是 | 无 |
|
||||
| `output` | map | 否 | 见下文 |
|
||||
| `generation` | map | 否 | 见下文 |
|
||||
| `formatting` | map | 否 | 见下文 |
|
||||
|
||||
必须至少配置一个启用的 `input.swagger_urls` 项。
|
||||
|
||||
## `input`
|
||||
|
||||
### `input.swagger_urls`
|
||||
|
||||
类型:字符串或 source 对象的列表。默认:空,会报错。
|
||||
|
||||
```yaml
|
||||
input:
|
||||
swagger_urls:
|
||||
- ./openapi.yaml
|
||||
- url: https://example.com/openapi.json
|
||||
enabled: true
|
||||
- url: ./experimental.yaml
|
||||
enabled: false
|
||||
```
|
||||
|
||||
source 对象字段:
|
||||
|
||||
| 字段 | 类型 | 必填 | 默认值 | 含义 |
|
||||
|---|---|---:|---|---|
|
||||
| `url` | string | 是 | 无 | 本地路径、file URL 或 HTTP(S) URL |
|
||||
| `enabled` | boolean | 否 | `true` | 是否参与生成 |
|
||||
|
||||
source 按配置顺序处理。多个根文档会确定性合并;operation 冲突报错,component
|
||||
冲突会确定性改名并产生诊断。
|
||||
|
||||
## `output`
|
||||
|
||||
| 字段 | 类型 | 默认值 | 含义 |
|
||||
|---|---|---|---|
|
||||
| `base_dir` | string path | `./lib/src` | 生成代码公共根 |
|
||||
| `api_dir` | string path | `<base_dir>/api` | API 输出根 |
|
||||
| `models_dir` | string path | `<base_dir>/api_models` | model 输出根 |
|
||||
| `included_tags` | string list | 未设置 | 包含匹配 tag 的 operation |
|
||||
| `excluded_tags` | string list | 未设置 | 排除匹配 tag 的 operation |
|
||||
| `included_paths` | string list | 未设置 | 包含匹配的 OpenAPI path |
|
||||
| `excluded_paths` | string list | 未设置 | 排除匹配的 OpenAPI path |
|
||||
| `included_operations` | string list | 未设置 | 包含匹配 operation |
|
||||
| `excluded_operations` | string list | 未设置 | 排除匹配 operation |
|
||||
| `included_models` | string list | 未设置 | 把匹配 schema 加为生成根 |
|
||||
| `excluded_models` | string list | 未设置 | 排除匹配 model |
|
||||
| `split_by_tags` | boolean | `true` | 按 operation tag 拆分 API 文件 |
|
||||
| `extract_version_from_url` | boolean | `false` | 尝试从 source URL 提取分组版本 |
|
||||
| `clean_stale_files` | boolean | `true` | 安全删除不再生成的自有文件 |
|
||||
| `skip_if_unchanged` | boolean | `true` | spec、config 和内容未变时跳过写入 |
|
||||
| `manifest_path` | string path | `<project>/.dart_tool/koi_swagger_parser/manifest.json` | 所有权/hash manifest |
|
||||
|
||||
过滤项支持:
|
||||
|
||||
- 精确字符串;
|
||||
- `*`、`?`、`**` glob;
|
||||
- `regex:<expression>`,使用 Dart 正则语法。
|
||||
|
||||
同一值同时匹配 include/exclude 时,exclude 优先;相同字面量同时出现在两边会
|
||||
产生 warning。若保留的 operation 依赖被排除 model,生成会失败,不会输出无法
|
||||
编译的客户端。
|
||||
|
||||
stale cleanup 仅处理旧 manifest 记录、仍位于当前 API/model 根、且内容仍匹配
|
||||
旧 hash 的文件。manifest 应放在生成的 API/model 根之外。
|
||||
|
||||
## `generation.preset`
|
||||
|
||||
| 字段 | 类型 | 默认值 | 可选值 |
|
||||
|---|---|---|---|
|
||||
| `name` | string | `koi_flutter` | `koi_flutter` |
|
||||
|
||||
当前版本只有一个 renderer preset:Dio + Retrofit API 和
|
||||
Freezed/json_serializable model。
|
||||
|
||||
## `generation.api`
|
||||
|
||||
| 字段 | 类型 | 默认值 | 可选值/含义 |
|
||||
|---|---|---|---|
|
||||
| `enabled` | boolean | `true` | 生成 API |
|
||||
| `use_retrofit` | boolean | `true` | 启用 API 时必须为 `true` |
|
||||
| `cancel_token_support` | boolean | `false` | 添加 Dio `CancelToken` 参数 |
|
||||
| `response_mode` | string | `body` | `body`、`http_response` |
|
||||
| `binary_response_mode` | string | `bytes` | `bytes`、`stream` |
|
||||
|
||||
`generation.api.enabled: true` 要求 `generation.models.enabled: true`,因为
|
||||
当前 Retrofit renderer 会导入生成的 model index。
|
||||
|
||||
### `generation.api.client`
|
||||
|
||||
| 字段 | 类型 | 默认值 | 含义 |
|
||||
|---|---|---|---|
|
||||
| `class_name` | string | `ApiClient` | 生成的 client class 名 |
|
||||
| `file_name` | string | `api_client` | 生成的 client 文件名 |
|
||||
|
||||
值会转换为安全的 Dart identifier/file name。
|
||||
|
||||
### `generation.api.response_wrapper`
|
||||
|
||||
| 字段 | 类型 | 默认值 | 可选值/含义 |
|
||||
|---|---|---|---|
|
||||
| `mode` | string | `passthrough` | `passthrough`、`external_generic` |
|
||||
| `success_data_field` | string | `data` | envelope 中的成功 payload 字段 |
|
||||
| `detect_standard_envelope` | boolean | `true` | 检测配置的 code/message/data 风格 envelope |
|
||||
| `external_generic.import` | string | 无 | `external_generic` 模式必填 |
|
||||
| `external_generic.class_name` | string | `BaseResult` | 外部 generic wrapper 类型 |
|
||||
|
||||
```yaml
|
||||
generation:
|
||||
api:
|
||||
response_wrapper:
|
||||
mode: external_generic
|
||||
success_data_field: data
|
||||
detect_standard_envelope: true
|
||||
external_generic:
|
||||
import: package:your_network/your_network.dart
|
||||
class_name: BaseResult
|
||||
```
|
||||
|
||||
兼容字段 `generation.api.base_result_import` 会在未显式设置 mode 时选择
|
||||
`external_generic`,class name 为 `BaseResult`。新配置应优先使用结构化写法。
|
||||
|
||||
## `generation.models`
|
||||
|
||||
| 字段 | 类型 | 默认值 | 含义 |
|
||||
|---|---|---|---|
|
||||
| `enabled` | boolean | `true` | 生成 model |
|
||||
| `class_prefix` | string | `Koi` | 生成 model 名称前缀 |
|
||||
| `default_non_nullable_list_to_empty` | boolean | `true` | 符合条件的非空 list 默认使用空 list |
|
||||
| `enum_unknown_fallback` | boolean | `false` | 生成并使用 `unknown` enum 成员 |
|
||||
| `enum_unknown_default_case` | boolean | `false` | 上一字段的兼容别名 |
|
||||
|
||||
### `generation.models.json_serializable`
|
||||
|
||||
| 字段 | 类型 | 默认值 |
|
||||
|---|---|---|
|
||||
| `checked` | boolean | `true` |
|
||||
| `explicit_to_json` | boolean | `true` |
|
||||
| `include_if_null` | boolean | `false` |
|
||||
|
||||
这些值会在适用场景传给生成的 json_serializable annotation。
|
||||
|
||||
### Enum 映射
|
||||
|
||||
支持 list 和 map 两种写法:
|
||||
|
||||
```yaml
|
||||
generation:
|
||||
models:
|
||||
enum_mappings:
|
||||
OrderStatus:
|
||||
- value: pending
|
||||
name: waitingForPayment
|
||||
description: 等待付款
|
||||
- value: done
|
||||
name: completed
|
||||
Priority:
|
||||
1: low
|
||||
2:
|
||||
name: high
|
||||
description: 需要关注
|
||||
```
|
||||
|
||||
外层 key 是 OpenAPI enum/schema 名称。wire `value` 可以是 string、number 或
|
||||
boolean;`name` 必须是非空 Dart 成员名;`description` 可选。
|
||||
|
||||
兼容字段 `enum_key_mappings` 接受同样结构。两个字段映射同一 enum value 时,
|
||||
`enum_mappings` 优先并产生 warning。vendor extension 优先级见
|
||||
[README 的 Enum 映射](../../README.zh-CN.md#enum-映射)。
|
||||
|
||||
## `generation.mappings`
|
||||
|
||||
所有 mapping 段默认都是空 map。
|
||||
|
||||
| 字段 | 结构 | 含义 |
|
||||
|---|---|---|
|
||||
| `models` | `schema: DartName` | 重命名生成的 component model |
|
||||
| `properties` | `schema: {wireProperty: dartField}` | 重命名指定 schema 的属性 |
|
||||
| `parameters` | `operation: {wireParameter: dartParameter}` | 重命名指定 operation 的参数 |
|
||||
| `operations` | `operation: dartMethod` | 重命名 operation |
|
||||
| `schemas` | `schema: type-or-object` | 使用外部 Dart 类型,不生成该 schema |
|
||||
| `types` | `openapiType[:format]: type-or-object` | 映射 OpenAPI scalar/type pattern |
|
||||
| `imports` | `DartType: packageImport` | 为映射后的 Dart 类型提供 import |
|
||||
|
||||
operation key 可以是 `operationId` 或 `METHOD /path`。type mapping 先尝试
|
||||
`type:format`,再尝试 `type`。
|
||||
|
||||
type-or-object 可以是 Dart 类型字符串,也可以是:
|
||||
|
||||
```yaml
|
||||
type: UuidValue
|
||||
import: package:uuid/uuid_value.dart
|
||||
```
|
||||
|
||||
同一 mapping scope 内,两个 source name 不能指向同一个 Dart 名。相同 schema
|
||||
不能同时出现在 `models` 和 `schemas`。同一个 Dart 类型不能解析出冲突 import。
|
||||
这些组合都会报配置错误。
|
||||
|
||||
## `formatting`
|
||||
|
||||
| 字段 | 类型 | 默认值 | 可选值/含义 |
|
||||
|---|---|---|---|
|
||||
| `run_dart_fix` | boolean | `false` | 对本轮改变的主生成文件执行 `dart fix --apply` |
|
||||
| `run_dart_format` | boolean | `true` | 格式化本轮改变的主生成文件 |
|
||||
| `run_build_runner` | boolean | `false` | 主文件写入后运行 build_runner |
|
||||
| `build_runner_mode` | string | `build` | `build`、`watch` |
|
||||
| `delete_conflicting_outputs` | boolean | `true` | 向 build_runner 传入 `--delete-conflicting-outputs` |
|
||||
|
||||
CLI `--watch` 会在非 dry-run 生成后启动 build_runner watch,不受配置 mode
|
||||
限制。watch 是长驻流程,适合交互式开发,不适合一次性 CI job。
|
||||
|
||||
## 组合规则
|
||||
|
||||
加载器会强制以下关系:
|
||||
|
||||
- API 和 model 不能同时关闭;
|
||||
- API 当前依赖 model;
|
||||
- API 当前要求 `use_retrofit: true`;
|
||||
- `external_generic` response wrapper 需要非空 import;
|
||||
- 未知 preset、enum/response/build-runner mode 会报错;
|
||||
- 非法 filter 正则会报错;
|
||||
- mapping target/import 冲突会报错。
|
||||
|
||||
稳定 code 和处理方式见[诊断参考](DIAGNOSTICS.md)。
|
||||
@@ -0,0 +1,150 @@
|
||||
# 诊断
|
||||
|
||||
[English](../DIAGNOSTICS.md) | [简体中文](DIAGNOSTICS.md)
|
||||
|
||||
配置、加载、解析、渲染和生命周期问题统一表示为 `KoiDiagnostic`:
|
||||
|
||||
```dart
|
||||
class KoiDiagnostic {
|
||||
final String code;
|
||||
final DiagnosticSeverity severity; // info | warning | error
|
||||
final String message;
|
||||
final String? source;
|
||||
final String? location;
|
||||
}
|
||||
```
|
||||
|
||||
`code` 是稳定的机器可读标识;message 文案可能随版本改进。`source` 表示配置
|
||||
路径、文档 URL/文件或生成文件;`location` 通常是 source 内的 JSONPath、
|
||||
JSON Pointer 或其他逻辑位置。
|
||||
|
||||
## Severity 行为
|
||||
|
||||
- `info`:正常决策,例如跳过未变化的生成;
|
||||
- `warning`:输出仍然可靠,但发生改名、安全降级或明确省略的非阻塞能力;
|
||||
- `error`:继续执行可能产生无效客户端,生成器抛出
|
||||
`KoiDiagnosticException`。
|
||||
|
||||
CLI 默认输出 warning/error;`--verbose` 还会输出 info 和失败堆栈。
|
||||
|
||||
library 调用方可检查诊断:
|
||||
|
||||
```dart
|
||||
try {
|
||||
final result = await const KoiSwaggerParser().generate();
|
||||
for (final item in result.diagnostics) {
|
||||
print(item.format());
|
||||
}
|
||||
} on KoiDiagnosticException catch (error) {
|
||||
for (final item in error.diagnostics) {
|
||||
print(item.format());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
自动化应匹配 `code`,不要匹配 message 文本。需要区分上下文时再断言 `source`
|
||||
或 `location`。
|
||||
|
||||
## 常见 code
|
||||
|
||||
### 配置
|
||||
|
||||
| Code | 含义和处理 |
|
||||
|---|---|
|
||||
| `config.missing_sources` | 添加至少一个启用的 `input.swagger_urls`。 |
|
||||
| `config.unknown_key` | 修正拼写或删除当前版本不认识的字段;warning。 |
|
||||
| `config.invalid_section` | 把 scalar/list 改成预期 YAML map。 |
|
||||
| `config.invalid_string` / `config.invalid_boolean` | 修正 YAML scalar 类型。 |
|
||||
| `config.invalid_string_list` | include/exclude filter 必须是字符串列表。 |
|
||||
| `config.invalid_filter_regex` | 修正 `regex:` 后的 Dart 表达式。 |
|
||||
| `config.no_outputs_enabled` | API/model 不能同时关闭。 |
|
||||
| `config.api_requires_models` | 当前 API renderer 依赖生成 model。 |
|
||||
| `config.unsupported_api_renderer` | 保持 `use_retrofit: true`;目前没有其他公开 API renderer。 |
|
||||
| `config.external_wrapper_import_required` | 添加 `external_generic.import`。 |
|
||||
| `config.mapping_target_collision` | 为 mapping source 设置不同的 Dart 目标名。 |
|
||||
| `config.import_mapping_conflict` | 同一映射 Dart 类型只能使用一个 import。 |
|
||||
| `config.conflicting_schema_mapping` | 同一 schema 不能既重命名又由外部类型替换。 |
|
||||
| `config.ambiguous_enum_mapping` | 使用类型明确、无歧义的 enum wire value。 |
|
||||
|
||||
### 文档与引用
|
||||
|
||||
| Code | 含义和处理 |
|
||||
|---|---|
|
||||
| `openapi.missing_version` / `openapi.unsupported_version` | 提供 OpenAPI 3.0.x/3.1.x 文档。 |
|
||||
| `openapi.invalid_info` / `openapi.invalid_paths` | 修正文档对应关键结构。 |
|
||||
| `openapi.source_load_failed` / `openapi.source_http_error` | 检查文件路径、URL、访问权限和响应状态。 |
|
||||
| `openapi.unresolved_ref` | 本地 JSON Pointer 不存在。 |
|
||||
| `openapi.unresolved_external_ref` | 外部资源/fragment 不存在或无法加载。 |
|
||||
| `openapi.external_ref_not_bundled` | ref 归一化失败;检查前序 source/resolver 诊断。 |
|
||||
| `openapi.external_component_renamed` | 外部 component 冲突已确定性改名;warning。 |
|
||||
| `openapi.multisource_component_renamed` | root 间 component 冲突已确定性改名;warning。 |
|
||||
| `openapi.multisource_operation_conflict` | 两个 root 定义相同 method/path;删除或拆分其中一个。 |
|
||||
| `openapi.callbacks_not_supported` / `openapi.webhooks_not_supported` | 不生成反向调用 client;warning。 |
|
||||
| `openapi.links_not_supported` | 不生成 Link Object 调用关系;warning。 |
|
||||
|
||||
### Parameter、request 与 response
|
||||
|
||||
| Code | 含义和处理 |
|
||||
|---|---|
|
||||
| `openapi.invalid_parameter_style` | 使用与 parameter location 匹配的 style。 |
|
||||
| `openapi.deep_object_requires_object` | deepObject parameter 必须使用 object schema。 |
|
||||
| `openapi.delimited_parameter_requires_array` | space/pipe-delimited parameter 必须使用 array schema。 |
|
||||
| `openapi.parameter_content_count` | Parameter Object `content` 必须恰有一个 media type。 |
|
||||
| `openapi.request_body_schema_missing` | 为选中的 request media type 添加 schema。 |
|
||||
| `openapi.unsupported_request_content_type` | 使用已支持 request codec 或手写 endpoint。 |
|
||||
| `openapi.unsupported_response_content_type` | 使用已支持 response codec 或手写 endpoint。 |
|
||||
| `openapi.success_response_missing` | 添加显式 2xx response;`default` 不是 success。 |
|
||||
| `openapi.multiple_success_response_types` | 多个成功 JSON body type 统一为 `Object?`;warning。 |
|
||||
| `openapi.mixed_success_media_types` | 单个生成方法无法安全 decode binary/stream + JSON success。 |
|
||||
| `openapi.path_parameter_forced_required` | 声明为 optional 的 path parameter 被强制为 required;warning。 |
|
||||
|
||||
### Schema 与命名
|
||||
|
||||
| Code | 含义和处理 |
|
||||
|---|---|
|
||||
| `openapi.property_read_write_only` | property 不能同时 read-only/write-only。 |
|
||||
| `openapi.invalid_additional_properties` | 使用 boolean 或 Schema Object。 |
|
||||
| `openapi.property_name_collision` | 自动 suffix 避免了 Dart field collision;warning。 |
|
||||
| `openapi.operation_name_collision` | 自动 suffix 避免了 method collision;warning。 |
|
||||
| `openapi.operation_argument_name_collision` | parameter 与 body、cancel token 或其他参数冲突。 |
|
||||
| `openapi.duplicate_enum_member_name` | 多个 wire value 映射到同名,已添加 suffix。 |
|
||||
| `openapi.enum_member_name_sanitized` | enum member name 已转换为合法 Dart identifier。 |
|
||||
| `filter.required_model_excluded` | 选中 API 依赖被排除 model;包含该 model 或排除调用方。 |
|
||||
| `filter.model_pattern_unmatched` | `included_models` pattern 没有匹配 schema。 |
|
||||
|
||||
### Server 与 security
|
||||
|
||||
| Code | 含义和处理 |
|
||||
|---|---|
|
||||
| `openapi.server_url_missing` | 添加非空 server URL。 |
|
||||
| `openapi.server_variable_default_missing` | 为每个 server variable 提供 default。 |
|
||||
| `openapi.server_variable_default_invalid` | 让 default 属于声明的 enum value。 |
|
||||
| `openapi.server_variable_unresolved` | 定义 server URL 中的每个 variable。 |
|
||||
| `openapi.unknown_security_scheme` | 在 components 中定义被引用 scheme。 |
|
||||
| `openapi.unsupported_security_scheme` | scheme 只在文档边界内保留或被拒绝。 |
|
||||
| `openapi.http_auth_requires_custom_interceptor` | 在宿主 Dio 层实现凭证注入;warning。 |
|
||||
|
||||
### 生成生命周期
|
||||
|
||||
| Code | 含义和处理 |
|
||||
|---|---|
|
||||
| `lifecycle.unchanged_skipped` | hash/file 一致,已安全跳过生成。 |
|
||||
| `lifecycle.manifest_invalid` | 旧 manifest 损坏;重建输出但不信任其删除列表。 |
|
||||
| `lifecycle.manifest_version_ignored` | manifest schema 不兼容,其删除列表被忽略。 |
|
||||
| `lifecycle.output_outside_managed_roots` | renderer 输出越过 API/model 根,已拒绝。 |
|
||||
| `lifecycle.duplicate_output_path` | 两个渲染文件以不同内容指向同一路径。 |
|
||||
| `lifecycle.stale_path_outside_roots` | 旧路径位于当前 root 外,因此保留。 |
|
||||
| `lifecycle.stale_file_modified` | stale 生成文件已被编辑,保留供人工处理。 |
|
||||
| `lifecycle.generated_file_missing` | 主生成文件在 fix/format/build 期间消失。 |
|
||||
| `lifecycle.control_file_not_stale` | lifecycle 控制文件永不作为 stale 输出处理。 |
|
||||
|
||||
## 设计原则
|
||||
|
||||
1. unresolved ref、非法 wire style 和不支持 codec 不会静默变成 `dynamic`;
|
||||
2. 安全且可编译的自动改名可以 warning 后继续;
|
||||
3. 不会破坏其他输出的不支持结构会 warning 后明确省略;
|
||||
4. stale cleanup 在 path containment 或 hash ownership 不确定时保留文件;
|
||||
5. 可用时诊断会带 component、operation、parameter 或文件上下文。
|
||||
|
||||
minor release 可以增加新 code。自动化应把未知 warning 视为需复核,把未知 error
|
||||
视为阻塞。
|
||||
@@ -0,0 +1,215 @@
|
||||
# 从 swagger_generator_flutter 迁移
|
||||
|
||||
[English](../MIGRATION.md) | [简体中文](MIGRATION.md)
|
||||
|
||||
本指南面向使用 `swagger_generator_flutter` 的 `generator_config.yaml` 惯例。
|
||||
迁移应在消费方 Dart/Flutter 仓库中进行,不依赖任何本机绝对路径。
|
||||
|
||||
## 建议顺序
|
||||
|
||||
1. 在独立分支保留旧生成结果;
|
||||
2. 复制 [koi_swagger_parser.example.yaml](../../koi_swagger_parser.example.yaml),
|
||||
第一轮只迁移 source、输出根和 response wrapper;
|
||||
3. 第一次设置 `clean_stale_files: false` 并执行 `--dry-run`;
|
||||
4. 生成到临时目录,对比 API signature、JSON key 和 import;
|
||||
5. 迁移 enum、命名和 custom type mapping;
|
||||
6. 在宿主项目运行 build_runner、`dart analyze` 和测试;
|
||||
7. 审核输出后切换正式目录,并启用 `clean_stale_files: true`。
|
||||
|
||||
## 可直接沿用
|
||||
|
||||
| 旧字段 | 新字段或行为 |
|
||||
|---|---|
|
||||
| `input.swagger_urls` | 同名;支持 string/object、`enabled`、本地路径和 HTTP(S) source |
|
||||
| `output.base_dir/api_dir/models_dir` | 同名 |
|
||||
| `output.included_tags/excluded_tags` | 同名,并支持 glob/正则 |
|
||||
| `output.split_by_tags` | 同名 |
|
||||
| `generation.api.client.class_name/file_name` | 同名 |
|
||||
| `generation.api.cancel_token_support` | 同名 |
|
||||
| `generation.api.base_result_import` | 兼容输入;选择 `external_generic` + `BaseResult` |
|
||||
| `generation.models.class_prefix` | 同名 |
|
||||
| `generation.models.json_serializable.*` | 同名 |
|
||||
| `generation.models.enum_key_mappings` | 仍然支持;建议迁移到 `enum_mappings` |
|
||||
| `formatting.run_dart_format` | 同名 |
|
||||
|
||||
已有 enum mapping 不需要立即重写:
|
||||
|
||||
```yaml
|
||||
generation:
|
||||
models:
|
||||
enum_key_mappings:
|
||||
TaskType:
|
||||
- value: 1
|
||||
name: spotCheck
|
||||
description: 抽查
|
||||
```
|
||||
|
||||
两个字段映射同一 wire value 时,`enum_mappings` 优先。生成器也识别
|
||||
`x-enumNames`、`x-enum-varnames` 和 `x-enum-values`。
|
||||
|
||||
## 需要改写
|
||||
|
||||
### Response wrapper
|
||||
|
||||
旧写法:
|
||||
|
||||
```yaml
|
||||
generation:
|
||||
api:
|
||||
base_result_type: BaseResult
|
||||
base_result_import: package:app/network/base_result.dart
|
||||
```
|
||||
|
||||
推荐写法:
|
||||
|
||||
```yaml
|
||||
generation:
|
||||
api:
|
||||
response_wrapper:
|
||||
mode: external_generic
|
||||
detect_standard_envelope: true
|
||||
success_data_field: data
|
||||
external_generic:
|
||||
import: package:app/network/base_result.dart
|
||||
class_name: BaseResult
|
||||
```
|
||||
|
||||
`base_page_result_type/base_page_result_import` 没有自动一对一迁移。优先在
|
||||
OpenAPI 中准确描述分页 schema;复用已有类型时使用
|
||||
`generation.mappings.schemas`,或用 `passthrough` 保留服务端 envelope。
|
||||
|
||||
### 类型与 import mapping
|
||||
|
||||
旧顶层 `type_mapping` 和 `imports` 是全局配置。新配置把可校验 mapping 集中到
|
||||
`generation.mappings`:
|
||||
|
||||
```yaml
|
||||
generation:
|
||||
mappings:
|
||||
schemas:
|
||||
Money:
|
||||
type: Money
|
||||
import: package:money2/money2.dart
|
||||
types:
|
||||
string:uuid:
|
||||
type: UuidValue
|
||||
import: package:uuid/uuid_value.dart
|
||||
string:date-time: DateTime
|
||||
imports:
|
||||
UuidValue: package:uuid/uuid_value.dart
|
||||
```
|
||||
|
||||
type 查找先尝试 `type:format`,再尝试 `type`。`schemas` 表示 schema 完全由
|
||||
external type 提供,不再生成对应 Dart model。
|
||||
|
||||
### ignored directory/file
|
||||
|
||||
旧 `ignored_directories`/`ignored_files` 在渲染后跳过文件,可能留下引用缺失
|
||||
model 的 API。应改为源语义 filter:
|
||||
|
||||
```yaml
|
||||
output:
|
||||
excluded_paths:
|
||||
- /api/v1/legacy/**
|
||||
excluded_operations:
|
||||
- regex:^internal
|
||||
excluded_models:
|
||||
- Legacy*
|
||||
```
|
||||
|
||||
保留的 operation 若依赖被排除 model,生成会以
|
||||
`filter.required_model_excluded` 失败。没有任意丢弃渲染文件的设置。
|
||||
|
||||
### 版本提取
|
||||
|
||||
`/api/v1/`、`/v2/` 等 path 会自动分组。若还要尝试从 source URL 提取:
|
||||
|
||||
```yaml
|
||||
output:
|
||||
extract_version_from_url: true
|
||||
```
|
||||
|
||||
旧 `generation.api.version_extraction.pattern/default_version` 没有一对一配置。
|
||||
URL 提取失败会产生诊断并回到基于 path 的分组。
|
||||
|
||||
### build_runner
|
||||
|
||||
旧流程通常单独执行 build_runner,现在可以并入生成:
|
||||
|
||||
```yaml
|
||||
formatting:
|
||||
run_dart_format: true
|
||||
run_build_runner: true
|
||||
build_runner_mode: build
|
||||
delete_conflicting_outputs: true
|
||||
```
|
||||
|
||||
交互式开发可用:
|
||||
|
||||
```bash
|
||||
dart run koi_swagger_parser generate --watch
|
||||
```
|
||||
|
||||
watch 是长驻模式,不适合一次性 CI job。
|
||||
|
||||
## 不再读取的旧设置
|
||||
|
||||
这些字段会产生 `config.unknown_key` warning:
|
||||
|
||||
- `generator.name/version/author/copyright`;
|
||||
- `input.validate_schema/strict_mode`;
|
||||
- `output.api_file_suffix/model_file_suffix`;
|
||||
- `generation.api.use_dio/parser/method_naming`;
|
||||
- `generation.models.class_naming/field_naming/use_const_constructor`;
|
||||
- 顶层 `validation.on_error/on_warning`;
|
||||
- 顶层通用 import 排序/分组设置。
|
||||
|
||||
新生成器对会破坏 wire semantics 或编译的情况使用结构化 error,不提供
|
||||
warn/ignore override。callbacks、links 等可安全省略的不支持结构使用 warning。
|
||||
|
||||
## 需审核的生成代码差异
|
||||
|
||||
- readOnly/writeOnly schema 可拆为 `FooRequest`/`FooResponse`;
|
||||
- optional 但 schema 不允许 null 的字段仍用 nullable Dart argument 表示 absent,
|
||||
同时使用 `disallowNullValue`;显式 JSON null 会被拒绝;
|
||||
- 根 object 同时有 `properties` 和 `additionalProperties` 时,extra 会 flatten
|
||||
到 JSON 根;
|
||||
- `default` response 永不作为 success;
|
||||
- 复杂 parameter style 可产生 public transport adapter + private Retrofit
|
||||
delegate;
|
||||
- API method 可返回 `HttpResponse<T>`,binary 输出可使用 bytes/stream;
|
||||
- enum 包含 wire conversion,unknown fallback 使用内部 sentinel wire value;
|
||||
- stale file 只通过 manifest ownership 删除;用户修改的 stale file 会保留。
|
||||
|
||||
## CLI 对照
|
||||
|
||||
旧:
|
||||
|
||||
```bash
|
||||
dart run swagger_generator_flutter generate --all
|
||||
```
|
||||
|
||||
新:
|
||||
|
||||
```bash
|
||||
dart run koi_swagger_parser generate --all
|
||||
dart run koi_swagger_parser generate --dry-run --verbose
|
||||
```
|
||||
|
||||
旧 `--api`、`--models`、`--docs` 和 CLI tag override 不再保留。使用
|
||||
`generation.*.enabled` 和 output filter。当前生成器不输出独立 API 文档站点。
|
||||
|
||||
## 验收清单
|
||||
|
||||
- dry-run 无 error 诊断;
|
||||
- enum wire value 和 Dart member name 与旧契约一致;
|
||||
- request/response directional model 包含预期字段;
|
||||
- cookie、query、path 序列化产生等价请求;
|
||||
- error/default response 不被 decode 成 success;
|
||||
- external custom type 的 import 和 JSON conversion 正确;
|
||||
- `dart run build_runner build --delete-conflicting-outputs` 成功;
|
||||
- `dart analyze` 和宿主项目测试通过;
|
||||
- 第二次生成报告 `lifecycle.unchanged_skipped`;
|
||||
- 移除 operation 后只删除 manifest 拥有且未修改的文件。
|
||||
|
||||
对每个可用后端 fixture,除了对比生成源码,还应对比 runtime serialization。
|
||||
Reference in New Issue
Block a user