41 lines
1.8 KiB
TypeScript
41 lines
1.8 KiB
TypeScript
|
|
// 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<string, MessageMappingProperties>,
|
|||
|
|
transform: (data: unknown) => Observable<unknown>,
|
|||
|
|
): Observable<unknown> {
|
|||
|
|
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));
|
|||
|
|
}
|
|||
|
|
}
|