Skip to content

packages/client 的 discovery 测试替身也拼 endpoints(#4828 退役键)、且 capabilities 拼成数组 #5787

Description

@baozhoutao

发现于 #5674 的实施(界外发现,查重无命中故新开;未认领;observation-class,今天没有用户会撞上)。

现象

#5674 清掉了 packages/rest/src 里 25 个拼 endpointsgetDiscovery 替身。repo 范围复查(按「规则的消费半径」而不是按被改的包扫)时,发现同一个退役键在另一个包里还活着一处:

packages/client/src/client.test.ts:36-44,connect() 的 discovery 响应替身:

const fetchMock = vi.fn().mockResolvedValue({
  ok: true,
  json: async () => ({
    version: 'v1',
    apiName: 'ObjectStack',
    capabilities: ['metadata', 'data', 'ui'],
    endpoints: {}
  })
});

两处与真实形状不符,方向不同:

  1. endpoints —— 真实 producer 发 routes(ApiRoutesSchema,DiscoverySchema 里必填),从来没发过 endpoints;该键只在 dispatcher 那条路径上作为 routes 的逐字副本存在过,两个 discovery 生产者都在线上返回 schema 未声明的顶层字段(scoping / features / endpoints),且 REST 形状永远无法通过 DiscoverySchema #4828 已按 ADR-0049 删除,并由三处 discovery-schema-conformance.test.ts 钉死。
  2. capabilities: ['metadata', 'data', 'ui'] —— DiscoverySchemacapabilities 声明为 Record (键 → { enabled, features?, description? }),不是字符串数组。这个替身描述的是一个更早的、且已经不存在的形状。

为什么今天没事

  • 生产类型是对的:DiscoveryResult = GetDiscoveryResponse(packages/client/src/index.ts:131),即 spec 类型,里面没有 endpoints;
  • packages/client/src 的生产代码没有一处discovery.endpoints(全仓 grep 只命中注释与无关的 auth/OAuth 端点措辞);
  • 该用例只断言 expect(fetchMock).toHaveBeenCalled(),不碰 body 的任何键。

所以它是惰性的 —— 和 #5674 里那 25 个替身完全同一个类别:替身描述了一个从未存在过(或早已改掉)的生产者形状,削弱了它作为「client 在真实上游之上做了什么」的证据力,并且是下一次复制粘贴的种子。

建议的修法

替身改成真实 /discovery body 的形状(routes: { data: '/api/v1/data', metadata: '/api/v1/meta' },capabilities 用 record 形态),tests-only。

#5674 的 PR 里已经加了一条 pin(packages/rest/src/discovery-double-retired-key.test.ts),但它按包扫描,只覆盖 packages/rest/src。修这一条时可以顺带判断:是把该 pin 提成跨包的 repo 级 gate,还是在 client 里放一条同样的本地 pin —— 这是个取舍,不要默认扩大。

参考:#5674#4828、ADR-0049。

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions