t3code 依赖的 @effect/openapi-generator:format 输出格式统一与 httpapi 生成能力解析
【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code
本文基于 Effect 仓库中的 changeset 变更记录 green-chips-wash.md,解读@effect/openapi-generator在 v4 公开迁移(public migration)中完成的一项关键接口变更:用统一的format选项与--formatCLI 参数取代旧的typeOnly布尔开关和--type-only标志,并新增httpapi输出格式。读完后,你将掌握三种输出格式(httpclient/httpclient-type-only/httpapi)的选型差异、完整 CLI 参数表、新旧参数的迁移方式,以及生成器内部的层(Layer)路由机制与警告输出约定。
一、变更背景:一个 changeset 说明了什么
在 Effect 生态的 pnpm workspace 中,.repos/effect-smol/.changeset/pre/green-chips-wash.md是一条标准的 Changesets 预发布变更说明,其内容为:
Finalize the OpenAPI generator public migration by replacing the
typeOnlyoption and--type-onlyCLI flag with theformatoption and--formatflag, and by addinghttpapias a supported output alongsidehttpclientandhttpclient-type-only.
拆解出三个要点:
- 旧 API 移除:
typeOnly生成选项与--type-only命令行标志被删除,且没有兼容别名——CLI 会直接拒绝该标志(后文有测试佐证); - 新 API 统一:所有输出形态收敛到一个
format选项 /--format标志,取值为枚举而非布尔组合; - 能力扩展:在原有的
httpclient与httpclient-type-only之外,新增httpapi输出,可以直接从 OpenAPI 规范生成 Effect 的HttpApi模块定义。
该包在仓库中的位置是.repos/effect-smol/packages/tools/openapi-generator,其 README 一句话概括了它的职责:Generates EffectSchematypes, HTTP clients, andHttpApimodules from OpenAPI specifications——即从 OpenAPI 规范生成 Effect 的 Schema 类型、HTTP 客户端和HttpApi模块。安装方式为(README 给出的官方命令):
npm install effect@rc @effect/openapi-generator@rc注意适用前提:当前仓库中该包处于 v4 预发布线(其 CHANGELOG 最新条目为4.0.0-rc.112),--format语义以当前仓库源码为准。
二、三种format输出格式及其路由机制
2.1OpenApiGenerateOptions:format 成为核心选项
生成器入口选项定义在 src/OpenApiGenerator.ts 中(标注@since 4.0.0):
export interface OpenApiGenerateOptions { /** The name to give to the generated output. */ readonly name: string /** The output format to generate. */ readonly format: OpenApiGeneratorFormat /** Hook to transform each JSON Schema node before processing. */ readonly onEnter?: ((js: JsonSchema.JsonSchema) => JsonSchema.JsonSchema) | undefined /** Callback to receive non-fatal generation warnings. */ readonly onWarning?: ((warning: OpenApiGeneratorWarning) => void) | undefined }从源码结构看,format与name是两个必填项,onEnter允许在 JSON Schema 节点被处理前做整体变换(例如批量改写字段类型),onWarning接收非致命告警。告警类型OpenApiGeneratorWarning包含code(如naming-collision、security-and-downgraded、default-response-remapped等枚举码)、message,以及可选的path/method/operationId用于定位到具体操作。
2.2 CLI 侧的层路由:为什么 type-only 走不同 Layer
CLI 入口 src/main.ts 中的关键片段:
const format = Flag.choice("format", ["httpclient", "httpclient-type-only", "httpapi"] as const).pipe( Flag.withAlias("f"), Flag.withDescription( "Output format to generate: httpclient | httpclient-type-only | httpapi (default: httpclient)" ), Flag.withDefault("httpclient") )并在命令装配时按format值选择不同的转换层:
Command.provide(({ format }) => format === "httpclient-type-only" ? OpenApiGenerator.layerTransformerTs : OpenApiGenerator.layerTransformerSchema )也就是说,httpclient-type-only使用纯 TypeScript 变换器(layerTransformerTs),而httpclient与httpapi都走 Schema 变换器(layerTransformerSchema)。这与输出产物一致:type-only 模式生成的代码只含类型导入,不导入运行时Schema。
三、完整 CLI 参数参考
结合 src/main.ts 中的 Flag 定义,当前openapigen命令的完整参数如下:
| 参数 | 别名 | 取值 / 默认值 | 说明 |
|---|---|---|---|
--spec | -s | 文件路径(必填) | 用于生成输出的 OpenAPI 规范文件 |
--name | -n | 字符串,默认Client | 生成产物的命名(如客户端类名 / HttpApi 名称) |
--format | -f | httpclient|httpclient-type-only|httpapi,默认httpclient | 输出格式 |
--patch | -p | 0 次到任意次;文件路径(.json/.yaml/.yml)或内联 JSON 数组 | 生成前按顺序对 OpenAPI 规范应用的 JSON Patch |
使用示例:
# 默认格式(httpclient),生成名为 ApiClient 的完整客户端 npx openapigen --spec openapi.json --name ApiClient # 仅类型输出,供纯类型消费的场景 npx openapigen -s openapi.json -n ApiClient -f httpclient-type-only # 生成 HttpApi 模块定义 npx openapigen -s openapi.json -n ApiClient -f httpapi # 先打补丁再生成(多个 patch 按顺序应用) npx openapigen -s openapi.json -p ./fix-security.json -p '[{"op":"replace","path":"/info/version","value":"2.0.0"}]'行为约定(由 CLI 实现与测试共同确认):
- 生成结果写入stdout;
- 所有告警通过
onWarning回调收集后写入stderr,格式为WARNING [code] METHOD path (operationId): message(见 src/main.ts 中的formatWarning函数),因此 stdout 可安全重定向为源文件而不被日志污染; - Patch 解析或应用失败会转成
CliError.UserError以非零退出码结束。
四、行为验证:CLI 测试用例逐条印证
测试文件 test/OpenApiGeneratorCli.test.ts 以子进程方式实际运行 CLI,恰好完整覆盖本条 changeset 宣称的三项变更:
--help文档化新参数:断言--help输出包含--format、三个取值(httpclient/httpclient-type-only/httpapi)以及default: httpclient字样;- 三种格式的路由与产物特征:
- 不传
--format时输出与显式--format httpclient完全一致,且包含import * as Schema from "effect/Schema"(运行时 Schema 导入); httpclient-type-only产物不包含上述运行时导入,而是import type * as HttpClient from "effect/unstable/http/HttpClient"(纯类型导入);httpapi产物包含export class CliClient extends HttpApi.make("CliClient"),即生成一个继承自HttpApi.make的 HttpApi 模块类;
- 不传
- 旧标志被硬性拒绝:传入
--type-only时进程以失败退出,stdout 打印USAGE,stderr 输出Unrecognized flag: --type-only——确认这是无兼容期的直接移除,而非 deprecated 别名; - stdout/stderr 分流:告警只进 stderr,保证 stdout 恒为可重定向的生成源码。
五、迁移指引:typeOnly 到 format 的对照
对于从 v4 迁移过程中仍在使用旧接口的代码,对照关系如下:
| 旧 API(已移除) | 新 API | 说明 |
|---|---|---|
typeOnly: false(或不传) | format: "httpclient" | 完整客户端,含运行时 Schema |
typeOnly: true | format: "httpclient-type-only" | 仅类型输出 |
| — | format: "httpapi" | 新增:生成HttpApi模块定义 |
--type-only标志 | --format httpclient-type-only(或-f) | CLI 传入旧标志将直接报错 |
需要说明的是,httpapi与httpclient虽共用同一个 Schema 变换层,但产物形态不同:前者生成HttpApi模块(API 定义侧,用于服务端或共享契约),后者生成HttpClient包装(调用侧)。选型上,若目标是产出可复用的 API 契约模块,应选httpapi;若是生成调用远端服务的客户端封装,选httpclient;若消费端只需要类型而不想引入运行时依赖,选httpclient-type-only。
六、延伸阅读
- 包入口与 CLI 实现:src/main.ts、src/bin.ts(Node 运行时入口,通过
NodeServices.layer提供平台服务); - 核心生成逻辑与选项定义:src/OpenApiGenerator.ts;
- Patch 机制(
--patch的解析与应用):src/OpenApiPatch.ts 及测试 test/OpenApiPatch.test.ts; - 生成产物断言(含 JSON Schema 生成细节):test/OpenApiGenerator.test.ts、test/JsonSchemaGenerator.test.ts;
- 包版本与依赖锁定信息:CHANGELOG.md(该包在 workspace 的 changeset 配置 中被列入
fixed固定版本组,与effect主包等同步发版)。
综合来看,这条 changeset 所代表的变更是@effect/openapi-generatorv4 公开 API 收尾的一步:以枚举化的format取代布尔开关,让"生成什么形态"成为单一显式决策点,同时把HttpApi模块生成纳入同一入口,使客户端生成、类型生成与服务端 API 定义生成共享同一套规范解析与 Patch 管线。
【免费下载链接】t3code项目地址: https://gitcode.com/GitHub_Trending/t3/t3code
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考