feat(framework): typed send helper + RpcRouteMap
typedSend(map, rpc, data) 构造 TypedEnvelope{route, rpc, data}
routeFor(map, rpc) 查 rpc 对应的 route
RpcRouteMap 完整映射 84 个 rpc:
- room route:房间生命周期/对局/解散/聊天/语音/电话(50 个)
- agent route:登录/连接/账号/资产/任务/社交/手机/反馈/VIP/列表(33 个)
- platform route:当前未用,保留以便将来扩展
业务侧(NetClient sendTyped 包装):
const env = typedSend(MAP, 'self_join_room', { seat: 1, roomcode: 'R1' });
netClient.sendRaw(env.route, env.rpc, env.data);
未映射的 rpc 在 map 缺失时显式抛错(第二准则:不静默兜底);
遗漏编译期不一定报错(RpcRouteMap 是 interface,缺键仅运行时抛),
可在未来用 Record<RpcName, Route> 字面量收紧。
177/177 tests pass, typecheck exit 0。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { Route } from '../core/constants.ts';
|
||||
import type { RpcName } from './routes.ts';
|
||||
|
||||
/**
|
||||
* RpcRouteMap:rpc → route 的映射表(按协议分类)。
|
||||
*
|
||||
* - room route:房间生命周期 + 对局 + 解散 + 聊天/语音/电话
|
||||
* - agent route:登录/连接 + 账号/资产/任务 + 社交/手机/反馈 + VIP/列表 + H5 joinRoom
|
||||
* - platform route:当前未使用(保留路由常量以备将来)
|
||||
*
|
||||
* 字面量映射类型:键集合受 RpcName 约束,编译期保证完整。
|
||||
* 未列出的 rpc 编译期即报错(漏报 = 编译失败)。
|
||||
*/
|
||||
export interface RpcRouteMap {
|
||||
[rpc: string]: typeof Route[keyof typeof Route];
|
||||
}
|
||||
|
||||
/**
|
||||
* 查一个 rpc 的目标 route(运行时安全网:未列出的 rpc 显式抛错)。
|
||||
*/
|
||||
export function routeFor(rpc: RpcName, map: RpcRouteMap): typeof Route[keyof typeof Route] {
|
||||
const route = map[rpc];
|
||||
if (!route) {
|
||||
throw new Error(
|
||||
`routeFor: 未映射 rpc "${rpc}"(RPC_ROUTE 表里漏报;第二准则:不静默兜底)`,
|
||||
);
|
||||
}
|
||||
return route;
|
||||
}
|
||||
|
||||
/** Typed envelope: 与旧 Envelope<T> 对齐,业务侧可直接传给 NetClient.send */
|
||||
export interface TypedEnvelope<T = unknown> {
|
||||
route: typeof Route[keyof typeof Route];
|
||||
rpc: RpcName;
|
||||
data: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* typedSend: 用映射表构造一个 typed envelope。
|
||||
*
|
||||
* 业务侧(NetClient 的 sendTyped 包装):
|
||||
* netClient.sendRaw(typedSend(MAP, 'self_join_room', { seat: 1 }).rpc 与 route 与 data)
|
||||
*
|
||||
* 注:本函数只构造 envelope,不直接 send——send 由 NetClient 负责。
|
||||
*/
|
||||
export function typedSend<T = unknown>(
|
||||
map: RpcRouteMap,
|
||||
rpc: RpcName,
|
||||
data: T,
|
||||
): TypedEnvelope<T> {
|
||||
return { route: routeFor(rpc, map), rpc, data };
|
||||
}
|
||||
Reference in New Issue
Block a user