Files
wwjcloud-nest-v1/wwjcloud-nest-v1/wwjcloud/libs/wwjcloud-boot/src/infra/websocket/ws-event-emitter.ts
wanwu 5f3b6f93b5 feat: Sprint1 完成 — NestJS特性补全+WebSocket+Docker+安全加固
3个并行智能体开发 + 审计智能体审查:

B1.1 ClassSerializerInterceptor:
- AppSerializerInterceptor 深度递归序列化
- @ExposeGroups() 分组控制字段暴露
- SysUser/Member password @Exclude()
- Member openid @Expose(groups:['owner'])

B1.2 自研限流增强:
- @Throttle() 装饰器支持路由级差异化配置
- X-RateLimit-Limit/Remaining/Reset 标准响应头
- skipIf 回调支持条件跳过
- 内存泄漏修复(60s定期清理)
- IP解析修复(取x-forwarded-for首个IP)
- 真正滑动窗口(时间戳队列)

B1.3 WebSocket Gateway:
- @WebSocketGateway /notifications 命名空间
- JWT认证握手 + userId→socketId映射
- WsNotificationEmitter 事件推送
- WsPushNotificationListener 事件桥接

安全加固(审计S7):
- CORS收紧(环境变量WS_ALLOWED_ORIGINS)
- WebSocket IP连接限流(MAX=10)
- Token仅通过auth传递(移除query)
- Member.idCard/MemberCashOutAccount.accountNo/Verify.code @Exclude()

Docker:
- 多阶段Dockerfile(deps→builder→runner)
- docker-compose.yml(app+mysql+redis+kafka+zk)
- E2E测试脚本 + 压力测试脚本(autocannon)

质量: tsc 0 error / eslint 0 error / any 0 / build ok
2026-04-15 16:40:31 +08:00

43 lines
1.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Injectable, Logger } from '@nestjs/common';
import {
NotificationGateway,
WS_NOTIFICATION_EVENT,
} from './notification.gateway';
/**
* WebSocket 通知事件发射器
* @description 封装 NotificationGateway 的推送能力,提供面向业务层的事件发射接口。
* 可被 Core 层的事件监听器注入使用,实现领域事件到 WebSocket 的桥接。
*/
@Injectable()
export class WsNotificationEmitter {
private readonly logger = new Logger(WsNotificationEmitter.name);
constructor(private readonly gateway: NotificationGateway) {}
/**
* 向指定用户推送 WebSocket 事件
* @param userId - 目标用户 ID
* @param event - 事件名称(默认使用 'notification'
* @param data - 事件负载数据
*/
async emitToUser(
userId: string,
event: string = WS_NOTIFICATION_EVENT,
data: unknown,
): Promise<void> {
if (!userId || typeof userId !== 'string') {
this.logger.warn('emitToUser called with invalid userId, skipping');
return;
}
try {
await this.gateway.sendToUser(userId, { event, data });
} catch (error) {
this.logger.error(
`Failed to emit WebSocket event to userId=${userId}: ${error instanceof Error ? error.message : String(error)}`,
);
}
}
}