Files
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

9.8 KiB
Raw Permalink Blame History

koi_swagger_parser

English | 简体中文

koi_swagger_parser 是面向 Dio、Retrofit、Freezed 和 json_serializable 项目的 OpenAPI 3.0/3.1 Dart/Flutter 客户端生成器。它将文档 加载、$ref 解析、校验、中间表示(IR)、渲染和安全的增量写入相互分离。

生成代码采用面向 Koi 项目的目录结构:

lib/src/
  api/
    api_client.dart
    index.dart
    v1/
      index.dart
      stores_api.dart
  api_models/
    api_models.dart
    request/
    result/
    shared/
    enums/

功能

  • 本地 JSON/YAML、HTTP(S)、多个根文档,以及本地、相对、file 和远程 $ref;
  • component 引用解析、缓存、循环检测、确定性冲突处理和依赖追踪;
  • Retrofit API,以及 Freezed/json_serializable 请求、响应、共享、枚举和联合模型;
  • enum_mappings、兼容字段 enum_key_mappings、x-enumNames、 x-enum-varnames、x-enum-values、描述和可选 unknown enum fallback;
  • model、property、parameter、operation、schema、type 和 import 映射及冲突诊断;
  • OpenAPI path、query、header 和 cookie 参数,包括已支持的 style、explode 和 allowReserved 组合;
  • JSON、text、multipart、form-urlencoded 和 binary 请求,以及 bytes/stream 下载;
  • 多个成功响应、204、2XX、default、错误响应、响应头和可选 HttpResponse<T> 返回值;
  • required、nullable、absent 语义,readOnly/writeOnly 投影, additionalProperties、allOf 和已支持的 oneOf/anyOf;
  • server variables 和 security metadata;凭证仍由宿主应用的 Dio interceptor 或 provider 注入;
  • 精确、glob 和正则过滤;
  • 带文件锁的 manifest、SHA-256 变更检测、安全 stale cleanup、原子写入、 dry-run 和可选 build_runner 集成。

准确边界见兼容性矩阵。

环境要求

  • Dart SDK ^3.11.0;
  • JSON 或 YAML 格式的 OpenAPI 3.0.x/3.1.x 文档;
  • 同时生成 API 和模型时,宿主 Dart/Flutter 项目需配置 Retrofit、Freezed 和 json_serializable。

安装

在宿主项目中把生成器添加为开发依赖:

dart pub add --dev koi_swagger_parser

典型生成客户端需要以下宿主运行时依赖:

dart pub add dio retrofit freezed_annotation json_annotation

添加相应代码生成工具:

dart pub add --dev build_runner retrofit_generator freezed json_serializable

Flutter 项目若统一使用 Flutter 管理依赖,可把 dart pub add 换成 flutter pub add。

快速开始

  1. 将完整配置模板复制为宿主项目中的 koi_swagger_parser.yaml。
  2. 至少设置一个 OpenAPI source 和输出目录:
input:
  swagger_urls:
    - url: ./openapi.json
      enabled: true

output:
  base_dir: ./lib/src
  api_dir: ./lib/src/api
  models_dir: ./lib/src/api_models

generation:
  preset:
    name: koi_flutter
  api:
    enabled: true
    use_retrofit: true
    response_wrapper:
      mode: passthrough
  models:
    enabled: true
    class_prefix: Koi

formatting:
  run_dart_format: true
  run_build_runner: true
  build_runner_mode: build
  1. 预览变更:
dart run koi_swagger_parser generate --all --dry-run
  1. 生成客户端:
dart run koi_swagger_parser generate --all

当 formatting.run_build_runner 为 false 时,单独执行:

dart run build_runner build --delete-conflicting-outputs

CLI 用法

dart run koi_swagger_parser generate [options]

--all, -a       生成所有已启用资源;为了命令兼容而保留。
--config, -c    配置文件路径。
--cwd           宿主项目工作目录。
--dry-run       完成解析和渲染,但不写入或删除文件。
--watch         生成后启动 build_runner watch。
--verbose, -v   显示 info 诊断和失败堆栈。

加载器按以下顺序在工作目录中查找:

  1. koi_swagger_parser.yaml
  2. koi_swagger_parser.yml
  3. generator_config.yaml
  4. generator_config.yml

当 --config 指向当前目录外的文件且未设置 --cwd 时,配置文件目录会成为宿主 项目工作目录。相对 source 和输出路径始终以配置文件目录解析;--cwd 只改变 宿主项目命令的运行位置,不改变这些路径语义。

Library 用法

也可以通过 Dart API 使用相同流水线:

import 'package:koi_swagger_parser/koi_swagger_parser.dart';

Future<void> main() async {
  final result = await const KoiSwaggerParser().generate(
    configPath: 'koi_swagger_parser.yaml',
    dryRun: true,
  );

  print('${result.operationsCount} operations');
  print('${result.modelsCount} models');
  for (final diagnostic in result.diagnostics) {
    print(diagnostic.format());
  }
}

遇到 error 诊断时会抛出 KoiDiagnosticException。自动化应匹配诊断 code, 而不是 message 文本。详见诊断参考。

Enum 映射

可在配置中把枚举 wire value 映射成稳定的 Dart 成员名:

generation:
  models:
    enum_unknown_fallback: true
    enum_mappings:
      OrderStatus:
        - value: pending
          name: waitingForPayment
          description: 等待付款
        - value: done
          name: completed
          description: 已完成

也支持 map 写法:

generation:
  models:
    enum_mappings:
      OrderStatus:
        pending: waitingForPayment
        done:
          name: completed
          description: 已完成

兼容字段 enum_key_mappings 仍然可用。名称解析优先级为:

  1. enum_mappings
  2. enum_key_mappings
  3. x-enumNames、x-enum-names 或 x-enum-varnames
  4. x-enum-values
  5. 根据 wire value 自动生成的名称

描述优先采用配置,其次是 x-enumDescriptions、 x-enum-descriptions 和 x-enum-values.description。启用 enum_unknown_fallback: true 后,生成器会添加稳定的 unknown 成员,并在 枚举引用上应用 JsonKey.unknownEnumValue。

命名与类型映射

generation:
  mappings:
    models:
      UserDto: User
    properties:
      UserDto:
        user_id: id
    parameters:
      getUser:
        user_id: id
    operations:
      getUser: fetchUser
      "DELETE /api/v1/users/{id}": removeUser
    schemas:
      Money:
        type: Money
        import: package:money2/money2.dart
    types:
      string:uuid:
        type: UuidValue
        import: package:uuid/uuid_value.dart
      integer:int64: int
    imports:
      UuidValue: package:uuid/uuid_value.dart

operation 映射键可以是 operationId 或 METHOD /path。schema 映射表示该 schema 由外部实现,因此不会为其生成模型。外部类型必须提供生成用法所需的 JSON 转换能力。

响应与传输

generation:
  api:
    cancel_token_support: true
    response_mode: http_response       # body | http_response
    binary_response_mode: bytes        # bytes | stream
    client:
      class_name: ApiClient
      file_name: api_client
    response_wrapper:
      mode: external_generic           # passthrough | external_generic
      success_data_field: data
      detect_standard_envelope: true
      external_generic:
        import: package:your_network/your_network.dart
        class_name: BaseResult

当 Retrofit annotation 无法表达已支持的 matrix、label、cookie、deepObject 或 reserved-character 参数时,生成器会在私有 Retrofit delegate 前生成 typed transport adapter。default response 始终被视为错误响应。

过滤与生命周期

output:
  included_tags: [stores]
  excluded_paths: [/internal/**]
  included_operations: [getStore, "POST /api/v1/stores"]
  excluded_models: [Legacy*]
  clean_stale_files: true
  skip_if_unchanged: true
  manifest_path: ./.dart_tool/koi_swagger_parser/manifest.json

过滤器支持精确值、*、?、** glob,或带 regex: 前缀的 Dart 正则。 exclude 优先于 include。included_models 可把原本未被引用的 component 加为 生成根。

manifest 只记录本生成器拥有的文件。仅当旧生成文件仍位于配置的 API/model 输出根内,且内容仍与旧 manifest hash 相同时,stale cleanup 才会删除它。 被修改的文件及旁边的手写文件会保留。

限制

当前版本明确不生成:

  • Swagger/OpenAPI 2.0 客户端;
  • callbacks、webhooks 或 Link Object 调用链;
  • XML、Protobuf 或任意自定义 codec;
  • 完整 JSON Schema 2020-12;
  • server stub、mock server 或非 Dart 目标;
  • 可由外部接入的 renderer/template API。

不支持或存在信息损失的结构会产生结构化 warning/error,不会静默宣称完全 支持。为新的 schema corpus 引入本生成器前请查看兼容性。

文档

开发

dart pub get
dart format .
dart analyze
dart test
dart run tool/verify_generated_package.dart

最后一条命令会创建临时 Dart 包,调用本生成器及其 build_runner 集成,并在 生成的包内执行分析和运行时测试。

支持与贡献

请通过 GitHub Issues 提交可复现的问题和功能需求。请附带生成器版本、Dart 版本、最小 OpenAPI 文档、 相关配置和诊断 code;分享前移除凭证和私有服务数据。

贡献代码时应增加聚焦的测试;行为变化时同步兼容性矩阵和配置参考。提交 PR 前 请运行上述开发检查。

许可证

MIT