// services/api/src/realtime/contract-ws.adapter.ts —— 契约帧协议的 WS 适配器 // (P2 Task 7)。@nestjs/platform-ws 的 WsAdapter 只分发 {event,data} 信封 // 帧,而 P2 契约(@photo/contracts realtime.ts)的客户端消息是 {type,...} // 判别联合——本子类仅覆写 bindMessageHandler:按 frame.type 查处理映射, // 整帧作为载荷传入网关方法(@SubscribeMessage(type)),其余(同端口 HTTP // 挂载、upgrade 路由、关闭语义)全部继承 WsAdapter。非法 JSON / 非对象帧 / // 未知 type 静默丢弃(EMPTY)——协议层 error 帧只对「可理解但被拒绝」的 // 消息(如 subscribe 校验失败)由网关显式返回。 import { WsAdapter } from '@nestjs/platform-ws'; import type { MessageMappingProperties } from '@nestjs/websockets/gateway-metadata-explorer'; import { EMPTY, type Observable } from 'rxjs'; export class ContractWsAdapter extends WsAdapter { override bindMessageHandler( buffer: { data?: unknown }, handlersMap: Map, transform: (data: unknown) => Observable, ): Observable { let frame: unknown; try { frame = JSON.parse(String(buffer.data)); } catch { return EMPTY; } if (typeof frame !== 'object' || frame === null) { return EMPTY; } const { type } = frame as { type?: unknown }; if (typeof type !== 'string') { return EMPTY; } const handler = handlersMap.get(type); if (handler === undefined) { return EMPTY; } // 整帧作为载荷(网关方法按契约类型解构);返回值经 transform 送回客户端 // (返回 undefined/void 时上层 filter 掉,不发送——无应答语义的消息用此)。 return transform(handler.callback(frame, type)); } }