fix(client): 让 client 测试层真的进 tsc,那处 @ts-expect-error 不再是幽灵检查 - #5546
Merged
Conversation
…stops being a phantom check `packages/client/tsconfig.json` excludes `**/*.test.ts` and the package's `typecheck` script was a bare `tsc --noEmit` reading that same config, so no gate anywhere read a client test file with a type checker. The one `@ts-expect-error` in the package — `client.test.ts:1283` — evaluated never: on `origin/main`, deleting the directive line left `pnpm --filter @objectstack/client typecheck` just as green as leaving it there. Compiled for the first time, that directive reports TS2578 "unused". It never had anything to suppress: `project(environmentId: string)` accepts `''`, which is a perfectly good `string`, and the directive's own comment already said what the test proves — the empty id is rejected at RUNTIME. So the repair is to delete the directive, not to keep it: the reverse verification is the mirror of the usual one, and RESTORING the line is what now goes red. - `packages/client/tsconfig.test.json`: a sibling of the build config (which keeps its exclusion — ci.yml gates that no test file reaches the published artifact) with vitest's module semantics (`module: esnext`, `moduleResolution: bundler`, ES2022 lib) and `rootDir` widened to the workspace root, since four test files deep-import sibling packages' route ledgers. Strictness flags are inherited, untouched. - 13 errors surfaced; eight were the tests' own and are fixed here — two unused imports, an unused parameter, two possibly-undefined reads on an optional `routes` map, an `unknown` payload now asserted with `toMatchObject` instead of cast, a `reference_to` key the field schema never had (the lookup declared no target at all), and the phantom pin. Re-spelling that key uncovered one more of the remaining kind; the six that stay are one producer-side defect (#5543) held per file in `test-typecheck-debt.json`, EXACT and shrink-only. - `scripts/check-test-typecheck.mts`: PROMOTED from `packages/spec/scripts/`, parameterized with `--package`, so client onboards by wiring its `typecheck` script rather than by copying 300 lines. spec's ledger and its 79 files / 691 errors are unchanged, and the generated `_comment` is byte-identical. - Both graduations the gates force: `@objectstack/client` leaves TEST_DEBT (its stale entry measured 15 files / 19 errors, five of them the inherited-rootDir TS6059 that were the check's own misconfiguration) and its `PHANTOM_PIN_DEBT` seed — the entry #5478 left addressed to this issue — is deleted. Fixes #5449 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016FNvXhtSdnEGEfLEsMmvxh
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 113 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 5, 2026 16:57
baozhoutao
enabled auto-merge
August 5, 2026 16:57
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 #5449
照 #5286 / PR #5478 定下的机制跟进,不发明第二套。
前提复核(先证后改)
在最新
origin/main(9894a723e)上两态实测:packages/client/src/client.test.ts:1283的// @ts-expect-error — empty string rejected at runtime→pnpm --filter @objectstack/client typecheck退出码 0两态皆绿 = 该指令从未被求值。前提成立。
反向验证方向:与派发模板相反,如实申报
派发单预判「修好后删掉指令行应红 TS2578」。这个方向在本单不成立,而且是本单的核心发现:
project(environmentId: string)接受''—— 那就是一个合法的string—— 所以该指令从来没有东西可压制。它第一次被编译时报的就是也就是说,正确的修法就是删掉这行指令(它自己的注释已经说明了这个测试真正证明的事:空 id 是在运行时被下面那道 guard 拒绝的)。因此反向验证是镜像的:把指令行加回去应该红。先判后跑,实跑结果:
修改前同样的「加回去」是绿的,修改后是红的 —— 这正是「该文件现在真的在一个 tsc program 里」的证据。
做了什么
packages/client/tsconfig.test.json(新增):build config 的 sibling。build 的exclude保留不动(ci.yml 有「编译产物不得含测试文件」的闸门,已实跑pnpm --filter @objectstack/client build确认dist/无测试文件)。差异只在模块语义:module: esnext、moduleResolution: bundler、ES2022 lib,匹配 vitest 的真实执行方式;外加把rootDir放宽到工作区根 —— 有四个测试文件深引用兄弟包的 route ledger(../../runtime/src/route-ledger等),继承来的rootDir: ./src会为此报 5 条 TS6059,那是检查本身配错,不是测试的问题(它们正是该包 TEST_DEBT 陈旧条目的大头)。严格性 flags 一律继承,一条都没放宽。13 条错误,修掉 8 条真实缺陷:两个未使用的 import、一个未使用的形参、两处对可选
routes的可能为 undefined 的读取(改成可选读 + 断言,没有用!或?? {}兜底,map 缺失照样测试失败)、一处unknown载荷改用toMatchObject结构断言(不加 cast)、一个字段 schema 根本没有的reference_tokey(那个 lookup 此前没有声明任何目标),以及那处幽灵 pin。重新拼对reference之后又暴露出 1 条同族错误。剩下 6 条进 EXACT ratchet 台账:三个文件、一个根因 —— objectql 的
registerObject参数标成了 schema 的 OUTPUT 类型(z.infer)而非 INPUT(已另立 objectqlregisterObject的参数标成 schema 的 OUTPUT 类型(z.infer),合法的作者态字面量一律 TS2740 —— 这是 spec/client 两份测试层欠账的同一根因 #5543)。packages/client/test-typecheck-debt.json逐文件精确记账、只减不增;objectqlregisterObject的参数标成 schema 的 OUTPUT 类型(z.infer),合法的作者态字面量一律 TS2740 —— 这是 spec/client 两份测试层欠账的同一根因 #5543 修好那天台账会自动变红要求毕业,而不是烂在那里。pin 所在文件client.test.ts不在台账里,必须零错误 —— 上面的反向验证就是靠这一点成立的。scripts/check-test-typecheck.mts:从packages/spec/scripts/提升为共享脚本,用--package指定包。派发单明确要求「不要发明第二套」,而把 300 行脚本复制一份进 client 恰恰就是第二套。spec 侧只改package.json的两行脚本;其台账文件一字未动,生成的_comment模板与已存字节完全一致(未来--update不会产生伪 diff),实跑pnpm --filter @objectstack/spec check:test-typecheck仍为 79 文件 / 691 错误。两处台账毕业(闸门本身会强制):
@objectstack/client从TEST_DEBT删除(陈旧条目记 15 文件 / 19 错误,其中 5 条是上面说的 rootDir 误配),PHANTOM_PIN_DEBT里 fix(spec): 让 spec 测试层真的进 tsc,@ts-expect-error退役 pin 不再是幽灵检查 #5478 写明「留给 幽灵@ts-expect-error不止 spec:@objectstack/client也有 1 处落在 tsconfig 排除区内(全仓横扫结果) #5449」的 seed 条目删除。AGENTS.md里那一段随之更新:台账不再是 spec 专有,闸门是一个共享脚本,接入方式是接线而不是复制。验证
未做 / 界外
@ts-expect-error退役 pin 在packages/spec里是幽灵检查:tsconfig 把**/*.test.ts排除出唯一的tsc --noEmit#5286 留下的独立提案,越界另立单。顺带一提,check-type-check-coverage.mjs的PINS_CHECKED已经在做等价的事,且PHANTOM_PIN_DEBT对新增条目是关闭的。packages/runtime/**([17.0-rc2验收] 安全:REST /actions 与 /automation 派发路由缺少匿名拒绝门 —— 未认证调用者可触发 system 提权的 RLS/FLS 绕过写入 #5519 在飞)与packages/rest/**(fix(rest): 缺表错误只在「缺的正是所请求对象」时才判为 unknown object (#5462) #5530 在飞)。registerObject的参数标成 schema 的 OUTPUT 类型(z.infer),合法的作者态字面量一律 TS2740 —— 这是 spec/client 两份测试层欠账的同一根因 #5543(objectqlregisterObject参数类型 —— 6 条残留欠账的唯一根因)、packages/client/tests/integration/不在任何 tsconfig 里,且其中的client.discovery是早已不存在的属性(集成套件对着一个不存在的 API 断言) #5544(packages/client/tests/integration/不在任何 tsconfig 里,且断言了一个不存在的client.discovery)、client SDK 的meta.getItem没有声明返回类型(载荷为unknown),而并排的meta.getItems有 —— 同一表面上相邻两个方法的类型化不对等 #5545(meta.getItem缺返回类型声明,而并排的getItems有)。Changeset
纯测试层 + 工装,不发布任何行为变更,按仓里同类先例(PR #5478 同样未加 changeset)走
pr-automation.yml首选的第 2 条路径:请打skip-changeset标签,而不是塞一个空 changeset(空 changeset 是 changesets/action 的真实输入,全空会静默绿着停掉发布 —— #4898)。Generated by Claude Code