对齐游戏分发响应 DTO 的 Rust 与 TypeScript 字段

- 给 GameDistributionGameSummary 补 coverObjectKey / screenshots / publicationRevision,给 GameDistributionPrivateVersion 补 publicationRevision,与 game_payload / private_version_payload 实际发出的键一致
- packages/shared 的 GameDistributionGame.currentVersion 改为可选,并写明作者侧响应自带同一份 game_payload 但不发这一项
- 删掉 DTO 一致性门禁里豁免这 4 个字段的 TS_ONLY_FIELDS 白名单,现在任一方向多出字段都会失败
- 同步游戏分发里程碑第 6 条的取证与剩余缺口
This commit is contained in:
kdletters
2026-09-28 17:58:00 +08:00
parent 1b2bfa4e74
commit 46d8768529
4 changed files with 19 additions and 20 deletions
+3 -18
View File
@@ -5,7 +5,7 @@
// Rust 侧加字段而 TS 侧忘改时,只有跑起来才会发现。这里用一张显式映射表逐字段/逐变体比对:
// - 映射表同时是「哪些 Rust DTO 必须在 TS 里有对应类型」的清单;
// - `TS_ONLY_TYPES` 是「服务端手拼 JSON、没有 Rust 结构体」的说明清单;
// - `TS_ONLY_FIELDS` 记录已知的、有原因的响应侧附加字段。
// - 两侧字段必须逐一对齐,任一方向多出字段都会失败(没有白名单)。
// 任何一处没有分类的新类型、新字段都会让检查失败,避免静默漂移。
import fs from 'node:fs';
@@ -52,17 +52,6 @@ const TS_ONLY_TYPES = [
'GameDistributionCancelVersionResponse',
];
// 已知的响应侧附加字段:Rust 结构体描述请求侧视图,TS 类型描述响应视图。
// 只允许「TS 多出」这些字段;Rust 多出字段一律报错(TS 必须跟上)。
const TS_ONLY_FIELDS = {
GameDistributionGame: [
'coverObjectKey',
'screenshots',
'publicationRevision',
],
GameDistributionPrivateVersion: ['publicationRevision'],
};
function camelCase(value) {
return value.replace(/_([a-z0-9])/g, (_, char) => char.toUpperCase());
}
@@ -160,14 +149,10 @@ for (const [rustName, tsName] of PAIRS) {
`${tsName} 缺少字段/变体:${missingInTs.join(', ')}(${rustName} 已有)`,
);
}
const allowlist = new Set(TS_ONLY_FIELDS[tsName] ?? []);
const extraInTs = difference(
tsDefinition.members,
rustDefinition.members,
).filter((value) => !allowlist.has(value));
const extraInTs = difference(tsDefinition.members, rustDefinition.members);
if (extraInTs.length > 0) {
failures.push(
`${tsName} 多出未登记字段/变体:${extraInTs.join(', ')}(要么补进 TS_ONLY_FIELDS 并写明原因,要么在 Rust 侧补上)`,
`${tsName} 多出未登记字段/变体:${extraInTs.join(', ')}(要么在 Rust 侧补上,要么先确认真实响应不再发出)`,
);
}
}