feat: v3.2 类型安全 state + 全局响应信封 + 便利 schema#192
Merged
Conversation
register(fn: T) 改为 register(fn: Middleware):当 T=Middleware(createERest 锁定)时, handler 的 (ctx, next) 参数由 TS 自动推导,无需手写类型标注。 此前 register(fn: T) 中 T 是类级泛型,TS 无法从函数字面量反推参数类型,导致 ctx/next 始终 implicit any,使用者被迫手写标注或定义中间桥接类型。 全量 276 测试通过。
由 one-api phase2-server dogfooding 驱动的三块框架改进: - 痛点1:ctx.state 实例级泛型 StateMap,消除鉴权值 as 断言 - 痛点4:全局 response envelope + registerTyped 强制 return,删手写 ok()/fail() - 痛点3+6:z.anyObject() 便利别名 + 测试返回类型从 response schema 推导 向后兼容为硬约束:State 默认值/未注册 enveloper 维持 v3.1 行为。
按依赖顺序: - Task 1: z.anyObject() 便利别名 - Task 2: 测试 success<T>() 返回类型从 response schema 推导 - Task 3: typed state(ERest<State> 泛型)+ registerTyped handler 第二参数统一为 ctx - Task 4: 全局 response envelope + wrapWithEnvelope dispatcher 接入 - Task 5: setResponseEnvelopers 接受 testUnwrapper 便捷拆信封 - Task 6: one-api phase2-server 同步适配验证 关键时序:Task 3 统一 handler 签名(reply→ctx),后续 Task 测试均用新签名。 向后兼容为硬约束。
erest 导出的 z 新增 anyObject() 语义化别名,供「动态字段 body」场景使用。 用 Proxy 透传原生 z + 注入 anyObject,不污染 Zod 原生命名空间。 同时具名导出 zAnyObject 常量。
Task 1 subagent 擅自把 .sort() 改成 .toSorted(),引入 tsc 错误。 回归到原始 .sort()(原地排序,语义等价)。
- TestAgent.success<T>() 泛型化(默认 unknown 向后兼容) - buildTest<T> 透传泛型,getter 返回泛型函数表达式 - 调用侧 .get<UserVO>(path).success<UserVO>() 时 T 由 response schema 推导 - test-test.ts 新增运行时 + 类型层断言用例
- Context<State, Raw> / Middleware<State> 加泛型(默认 Record<string,unknown> 向后兼容) - ctx.state 类型安全;ctx.reply.raw 强类型(Raw 经 ERest<T,Raw,State> 锁定) - registerTyped handler 签名 (req, reply) → (req, ctx),ctx 含 ctx.reply - 三子包 createERest<State>() 透传 State 泛型 - 存量测试同步适配(reply → ctx.reply) - 新增 test-state-types(类型推导)+ state 跨中间件传递测试 - 顺手:isMissing 提到 compileValidate 外层(消除 oxlint scoping error)
- setResponseEnvelopers({success, error, testUnwrapper}):注册后 handler 进入 return 模式
- wrapWithEnvelope 工具:包装 dispatch,成功用 successEnveloper 包 return 值,错误用 errorEnveloper 包
- registerTyped wrappedHandler:统一 await handler 返回值,写入 __returned + __returnValue
- FrameworkAdapter.bindRoute + 三子包接入 envelopers 参数
- testUnwrapper 便捷入口(等价 setFormatOutput,供测试拆信封)
- 未注册 enveloper 时退化为原 dispatch(v3.1 向后兼容,零开销)
- 新增 test-envelope(成功/错误/undefined 三场景)
breaking: registerTyped handler 第二参数 reply→ctx;ctx.state 类型由 State 泛型驱动 新增: z.anyObject() / success<T>() / setResponseEnvelopers
- examples/src/api.js: registerTyped handler (req, reply) → (req, ctx),reply.xxx → ctx.reply.xxx - README.md: 代码示例与说明同步(ctx.reply / ctx.reply.raw 逃生舱) - 完整 test 全绿(lib 287 + example 13)
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #192 +/- ##
==========================================
+ Coverage 91.64% 92.47% +0.82%
==========================================
Files 28 28
Lines 2837 2882 +45
Branches 722 748 +26
==========================================
+ Hits 2600 2665 +65
+ Misses 235 215 -20
Partials 2 2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- erest-gen codegen 模板:(req, reply) → (req, ctx)(影响生成代码的用户) - erest-gen README 示例同步 - test-raw-types / test-builder-types:reply.raw → ctx.reply.raw - api.ts registerTyped JSDoc:(req, reply) → (req, ctx) - README 修正 sed 误伤的 ctx.ctx.reply
在现有测试文件补充(不新建): - test-envelope.ts: wrapWithEnvelope 6 分支单测(零开销退化/success包装/不二次包装/ error包装/re-throw/undefined)+ enveloper 模式下 response schema 校验(通过+失败) - test-router.ts: compose 洋葱模型 6 单测(顺序/终止/reject/同步抛错/重复next/空链) lib/adapters/utils.ts 覆盖率 27.77% → 100%,整体 92.33% 达标。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
由 one-api phase2-server dogfooding 驱动的三块 ergonomics 改进:
ERest<T, Raw, State>实例级泛型,ctx.state类型安全(消除鉴权值as断言)。State 须用typealias 定义。setResponseEnvelopers({success, error, testUnwrapper})注册后,registerTypedhandler 进入 return 模式(return data→ 框架自动包装信封),告别手写ok()/fail()+ 每处reply.json(ok(x))。z.anyObject()别名(等价z.object({}).catchall(z.unknown()));success<T>()返回类型从 response schema 推导。附带:
registerTypedhandler 第二参数从reply统一为ctx(Context<State, Raw>,含ctx.reply+ctx.state),保留 raw 逃生舱强类型。Breaking(仅当启用新特性时)
registerTypedhandler 签名(req, reply) => void→(req, ctx) => datactx.state类型由 State 泛型驱动(默认Record<string, unknown>向后兼容)详见
MIGRATION.md。Test Plan