fix(client): meta.getItem / meta.saveItem 在两个表面标上 spec 已声明的响应类型 (#5545) - #5946
Merged
Merged
Conversation
…onse types on both surfaces (#5545) `ObjectStackClient.meta` and `ScopedProjectClient.meta` each had a `getItem` and a `saveItem` with no return-type annotation, so `unwrapResponse` / `_unwrap` resolved with no type argument and callers got `unknown` — while the `getItems` one line above returned `GetMetaItemsResponse`. - `getItem` -> `Promise< GetMetaItemResponse >` (the `{ type, name, item }` envelope). Honest only since #5563 converged the route's cached and non-cached paths on that one shape. - `saveItem` -> `Promise< SaveMetaItemResponse >`, including the ADR-0008 OCC token `version`. Nameable only since #5745 completed that schema. Both types are re-exported from `@objectstack/client`. `client.test.ts`'s getItem assertion becomes typed field reads (`result.type` / `result.name`) with its `as any` dropped, and a new test pins the save response's OCC carriers. Reverse-verified: stripping the four annotations turns those reads red with TS18046. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DWUR56YsttL5sTF72Q75TQ
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 1 package(s): 14 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
baozhoutao
marked this pull request as ready for review
August 6, 2026 12:56
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.
Fixes #5545
前提复核(先证后改)
基线
origin/main@a6b3ee7a1。issue 的事实在最新 main 上仍然成立,行号已随 main 漂移::538ObjectStackClient.meta.getItemsPromise< GetMetaItemsResponse >:554ObjectStackClient.meta.getItemunwrapResponse(res)无泛型实参 →unknown:570ObjectStackClient.meta.saveItemunknown:4685ScopedProjectClient.meta.getItemsPromise< GetMetaItemsResponse >:4692ScopedProjectClient.meta.getItemparent._unwrap(res)无泛型实参 →unknown:4699ScopedProjectClient.meta.saveItemunknown同时复核了两个解锁前提,都已落地:
GET /meta/:type/:nameanswers two different body shapes on the same request — the cached branch (the DEFAULT) returns the bare document, the non-cached branch returns the spec-declared{ type, name, item }envelope #5563(PR fix(rest,runtime,client-react)!:GET /meta/:type/:name收敛到 spec 已声明的{type,name,item}信封,删掉isMetaEnvelope嗅探 (#5563) #5895,d9cac6019):GET /meta/:type/:name的缓存 / 非缓存两条分支现在都经RestServer.translateMetaEnvelope重建同一个信封(rest-server.ts:2714的注释把这点写死了:"This is the ONE place the single-item read paths rebuild their response body")。因此
GetMetaItemResponse现在是唯一诚实注解 —— 在GET /meta/:type/:nameanswers two different body shapes on the same request — the cached branch (the DEFAULT) returns the bare document, the non-cached branch returns the spec-declared{ type, name, item }envelope #5563 之前默认(缓存)分支发裸文档,任何一种注解都会在某种服务端配置下撒谎,这正是前任 dev 停手的理由。
SaveMetaItemResponseSchema已含version/seq/state/projectionApplied(protocol.zod.ts:273)。实测确认后才标注 —— 对着旧的{ success, message }声明标注会把 ADR-0008 OCC 令牌version从公开签名里抹掉,那才是前任 dev 拒标
saveItem的原因。改动
四处方法(两个表面 ×
getItem/saveItem)标上 spec 已声明的响应类型,类型从@objectstack/spec/apiimport 而非新增,与并排的getItems同源;两个类型同时加进packages/client既有的 spec 类型再导出块,调用方才有办法给收到的东西命名。packages/spec一字未动。测试
client.test.ts的 getItem 断言从toMatchObject权宜写法升级为类型化字段读取,as any一并摘掉(该 cast 存在的唯一理由就是这个表面没类型):result.item保持结构断言,不是遗漏:GetMetaItemResponseSchema里item就是z.unknown()(信封有类型,它装的文档没有),这是 schema 的形状本身。新增一条
saveItem测试,钉住 save 响应的 OCC 载体(version/seq/state);替身按真实路由构造 ——
rest-server.ts:4491是res.json(result),原样发协议层的返回对象。该测试的 getItem 替身在 #5563 里已翻成信封形状,本 PR 无需再翻。#5787 记录的替身问题
(
endpoints已退役、capabilities 形状错)不在本 PR 范围,未顺手修。命令与结果:
debt 账本未动(仍是 3 文件 / 6 错误,全部是 #5543 的 objectql
registerObjectINPUT/OUTPUT 类型问题),
client.test.ts不在账本里 —— 按该 gate 的口径,未列入的文件必须零错误。
反向验证(方向事先预测,结果一致)
预测:摘掉四处注解 → 载荷回落
unknown→ 类型化读取处报 TS18046。实测:注解恢复后归零。这条正是 #5449 在
client.test.ts(106,16)报的同一个错 —— 那次是测试层刚接进 tsc 时暴露的,这次是我们主动把它请回来确认新断言真的挂在注解上。
语义:为什么是 patch
公开签名从
unknown收窄。unknown不允许任何属性读取、也不能赋给有类型的绑定,所以改前能编译的表达式改后一样能编译;没有删除任何东西,没有新方法/新选项。非破坏,patch。
未做(明确留白)
meta.getHistory×2:spec 里没有任何 history 响应 schema,不凭空发明形状,保持现状。(另注:非作用域表面的那个已带手写内联形状,作用域表面的仍是
unknown—— 两者不对等,已在报告里留给 PM 转分诊。)
unwrapResponse< any >的meta.*方法(getPublished/listDrafts/migrateStored/getLegalNextStates/getDiagnostics/getReferences/getBookTree/getAudit/publishItem/rollbackItem/diffItem):产出any不是
unknown,且逐条补注解等于逐条定契约,前任 PM 已裁为另案。meta.getView:确实产出unknown,但不能标GetViewResponse—— 生产端getUiView发的是{ list: … }/{ form: … },spec 声明的是{ object, view },两者形状不同。这是
GET /meta/:type/:nameanswers two different body shapes on the same request — the cached branch (the DEFAULT) returns the bare document, the non-cached branch returns the spec-declared{ type, name, item }envelope #5563 同族的声明/实际背离,已另行立单,不在本 PR 修。data.*两个表面注解齐全(复核确认,无缺口)。