@roomkit/gateway 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +93 -0
  2. package/dist/src/admin/admin.controller.d.ts +187 -0
  3. package/dist/src/admin/admin.controller.d.ts.map +1 -0
  4. package/dist/src/admin/admin.controller.js +187 -0
  5. package/dist/src/admin/admin.controller.js.map +1 -0
  6. package/dist/src/admin/admin.module.d.ts +3 -0
  7. package/dist/src/admin/admin.module.d.ts.map +1 -0
  8. package/dist/src/admin/admin.module.js +28 -0
  9. package/dist/src/admin/admin.module.js.map +1 -0
  10. package/dist/src/admin/admin.service.d.ts +196 -0
  11. package/dist/src/admin/admin.service.d.ts.map +1 -0
  12. package/dist/src/admin/admin.service.js +322 -0
  13. package/dist/src/admin/admin.service.js.map +1 -0
  14. package/dist/src/config/config.module.d.ts +3 -0
  15. package/dist/src/config/config.module.d.ts.map +1 -0
  16. package/dist/src/config/config.module.js +22 -0
  17. package/dist/src/config/config.module.js.map +1 -0
  18. package/dist/src/config/config.service.d.ts +19 -0
  19. package/dist/src/config/config.service.d.ts.map +1 -0
  20. package/dist/src/config/config.service.js +55 -0
  21. package/dist/src/config/config.service.js.map +1 -0
  22. package/dist/src/config/gateway.config.d.ts +64 -0
  23. package/dist/src/config/gateway.config.d.ts.map +1 -0
  24. package/dist/src/config/gateway.config.js +43 -0
  25. package/dist/src/config/gateway.config.js.map +1 -0
  26. package/dist/src/connection/connection.module.d.ts +3 -0
  27. package/dist/src/connection/connection.module.d.ts.map +1 -0
  28. package/dist/src/connection/connection.module.js +22 -0
  29. package/dist/src/connection/connection.module.js.map +1 -0
  30. package/dist/src/connection/connection.service.d.ts +93 -0
  31. package/dist/src/connection/connection.service.d.ts.map +1 -0
  32. package/dist/src/connection/connection.service.js +257 -0
  33. package/dist/src/connection/connection.service.js.map +1 -0
  34. package/dist/src/gateway.module.d.ts +8 -0
  35. package/dist/src/gateway.module.d.ts.map +1 -0
  36. package/dist/src/gateway.module.js +44 -0
  37. package/dist/src/gateway.module.js.map +1 -0
  38. package/dist/src/index.d.ts +38 -0
  39. package/dist/src/index.d.ts.map +1 -0
  40. package/dist/src/index.js +97 -0
  41. package/dist/src/index.js.map +1 -0
  42. package/dist/src/lifecycle/graceful-shutdown.service.d.ts +65 -0
  43. package/dist/src/lifecycle/graceful-shutdown.service.d.ts.map +1 -0
  44. package/dist/src/lifecycle/graceful-shutdown.service.js +187 -0
  45. package/dist/src/lifecycle/graceful-shutdown.service.js.map +1 -0
  46. package/dist/src/lifecycle/index.d.ts +2 -0
  47. package/dist/src/lifecycle/index.d.ts.map +1 -0
  48. package/dist/src/lifecycle/index.js +18 -0
  49. package/dist/src/lifecycle/index.js.map +1 -0
  50. package/dist/src/main.d.ts +2 -0
  51. package/dist/src/main.d.ts.map +1 -0
  52. package/dist/src/main.js +56 -0
  53. package/dist/src/main.js.map +1 -0
  54. package/dist/src/metrics/metrics.controller.d.ts +13 -0
  55. package/dist/src/metrics/metrics.controller.d.ts.map +1 -0
  56. package/dist/src/metrics/metrics.controller.js +42 -0
  57. package/dist/src/metrics/metrics.controller.js.map +1 -0
  58. package/dist/src/metrics/metrics.module.d.ts +3 -0
  59. package/dist/src/metrics/metrics.module.d.ts.map +1 -0
  60. package/dist/src/metrics/metrics.module.js +26 -0
  61. package/dist/src/metrics/metrics.module.js.map +1 -0
  62. package/dist/src/metrics/metrics.service.d.ts +81 -0
  63. package/dist/src/metrics/metrics.service.d.ts.map +1 -0
  64. package/dist/src/metrics/metrics.service.js +255 -0
  65. package/dist/src/metrics/metrics.service.js.map +1 -0
  66. package/dist/src/ratelimit/rate-limit.module.d.ts +3 -0
  67. package/dist/src/ratelimit/rate-limit.module.d.ts.map +1 -0
  68. package/dist/src/ratelimit/rate-limit.module.js +23 -0
  69. package/dist/src/ratelimit/rate-limit.module.js.map +1 -0
  70. package/dist/src/ratelimit/rate-limiter.service.d.ts +68 -0
  71. package/dist/src/ratelimit/rate-limiter.service.d.ts.map +1 -0
  72. package/dist/src/ratelimit/rate-limiter.service.js +201 -0
  73. package/dist/src/ratelimit/rate-limiter.service.js.map +1 -0
  74. package/dist/src/redis/redis.module.d.ts +3 -0
  75. package/dist/src/redis/redis.module.d.ts.map +1 -0
  76. package/dist/src/redis/redis.module.js +22 -0
  77. package/dist/src/redis/redis.module.js.map +1 -0
  78. package/dist/src/redis/redis.service.d.ts +68 -0
  79. package/dist/src/redis/redis.service.d.ts.map +1 -0
  80. package/dist/src/redis/redis.service.js +281 -0
  81. package/dist/src/redis/redis.service.js.map +1 -0
  82. package/dist/src/session/session.module.d.ts +3 -0
  83. package/dist/src/session/session.module.d.ts.map +1 -0
  84. package/dist/src/session/session.module.js +21 -0
  85. package/dist/src/session/session.module.js.map +1 -0
  86. package/dist/src/session/session.service.d.ts +64 -0
  87. package/dist/src/session/session.service.d.ts.map +1 -0
  88. package/dist/src/session/session.service.js +206 -0
  89. package/dist/src/session/session.service.js.map +1 -0
  90. package/dist/src/ws/message-router.service.d.ts +133 -0
  91. package/dist/src/ws/message-router.service.d.ts.map +1 -0
  92. package/dist/src/ws/message-router.service.js +715 -0
  93. package/dist/src/ws/message-router.service.js.map +1 -0
  94. package/dist/src/ws/response-handler.service.d.ts +53 -0
  95. package/dist/src/ws/response-handler.service.d.ts.map +1 -0
  96. package/dist/src/ws/response-handler.service.js +282 -0
  97. package/dist/src/ws/response-handler.service.js.map +1 -0
  98. package/dist/src/ws/ws.gateway.d.ts +46 -0
  99. package/dist/src/ws/ws.gateway.d.ts.map +1 -0
  100. package/dist/src/ws/ws.gateway.js +244 -0
  101. package/dist/src/ws/ws.gateway.js.map +1 -0
  102. package/dist/src/ws/ws.module.d.ts +8 -0
  103. package/dist/src/ws/ws.module.d.ts.map +1 -0
  104. package/dist/src/ws/ws.module.js +39 -0
  105. package/dist/src/ws/ws.module.js.map +1 -0
  106. package/dist/test/connection/connection.service.spec.d.ts +2 -0
  107. package/dist/test/connection/connection.service.spec.d.ts.map +1 -0
  108. package/dist/test/connection/connection.service.spec.js +204 -0
  109. package/dist/test/connection/connection.service.spec.js.map +1 -0
  110. package/dist/test/e2e/gateway-worker.e2e.spec.d.ts +2 -0
  111. package/dist/test/e2e/gateway-worker.e2e.spec.d.ts.map +1 -0
  112. package/dist/test/e2e/gateway-worker.e2e.spec.js +412 -0
  113. package/dist/test/e2e/gateway-worker.e2e.spec.js.map +1 -0
  114. package/dist/test/integration/admin-api.spec.d.ts +2 -0
  115. package/dist/test/integration/admin-api.spec.d.ts.map +1 -0
  116. package/dist/test/integration/admin-api.spec.js +218 -0
  117. package/dist/test/integration/admin-api.spec.js.map +1 -0
  118. package/dist/test/ratelimit/rate-limiter.service.spec.d.ts +2 -0
  119. package/dist/test/ratelimit/rate-limiter.service.spec.d.ts.map +1 -0
  120. package/dist/test/ratelimit/rate-limiter.service.spec.js +139 -0
  121. package/dist/test/ratelimit/rate-limiter.service.spec.js.map +1 -0
  122. package/dist/test/setup.d.ts +2 -0
  123. package/dist/test/setup.d.ts.map +1 -0
  124. package/dist/test/setup.js +56 -0
  125. package/dist/test/setup.js.map +1 -0
  126. package/dist/test/ws/message-router.service.spec.d.ts +2 -0
  127. package/dist/test/ws/message-router.service.spec.d.ts.map +1 -0
  128. package/dist/test/ws/message-router.service.spec.js +403 -0
  129. package/dist/test/ws/message-router.service.spec.js.map +1 -0
  130. package/package.json +78 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-api.spec.js","sourceRoot":"","sources":["../../../test/integration/admin-api.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=rate-limiter.service.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.service.spec.d.ts","sourceRoot":"","sources":["../../../test/ratelimit/rate-limiter.service.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /// <reference types="jest" />
4
+ const rate_limiter_service_1 = require("../../src/ratelimit/rate-limiter.service");
5
+ describe('RateLimiterService', () => {
6
+ let service;
7
+ let configService;
8
+ beforeEach(() => {
9
+ configService = {
10
+ connectionRateLimit: 10,
11
+ messageRateLimitPerConnection: 5,
12
+ messageBurstLimit: 10,
13
+ globalMessageRateLimit: 100,
14
+ };
15
+ service = new rate_limiter_service_1.RateLimiterService(configService);
16
+ });
17
+ afterEach(() => {
18
+ jest.clearAllMocks();
19
+ });
20
+ describe('checkConnectionRate', () => {
21
+ it('should allow connections under the limit', () => {
22
+ for (let i = 0; i < 5; i++) {
23
+ expect(service.checkConnectionRate()).toBe(true);
24
+ }
25
+ });
26
+ it('should reject connections over the limit', () => {
27
+ // 使用所有配额
28
+ for (let i = 0; i < 10; i++) {
29
+ service.checkConnectionRate();
30
+ }
31
+ // 下一个连接应该被拒绝
32
+ expect(service.checkConnectionRate()).toBe(false);
33
+ });
34
+ it('should reset after window expires', async () => {
35
+ // 使用所有配额
36
+ for (let i = 0; i < 10; i++) {
37
+ service.checkConnectionRate();
38
+ }
39
+ expect(service.checkConnectionRate()).toBe(false);
40
+ // 等待窗口过期(1秒+)
41
+ await new Promise((resolve) => setTimeout(resolve, 1100));
42
+ // 现在应该允许
43
+ expect(service.checkConnectionRate()).toBe(true);
44
+ });
45
+ });
46
+ describe('checkMessageRate', () => {
47
+ const connectionId = 'conn-1';
48
+ it('should allow messages under the limit', () => {
49
+ for (let i = 0; i < 5; i++) {
50
+ const result = service.checkMessageRate(connectionId);
51
+ expect(result.allowed).toBe(true);
52
+ }
53
+ });
54
+ it('should reject messages over per-connection limit', () => {
55
+ // 使用所有配额
56
+ for (let i = 0; i < 5; i++) {
57
+ service.checkMessageRate(connectionId);
58
+ }
59
+ // 下一个消息应该被拒绝
60
+ const result = service.checkMessageRate(connectionId);
61
+ expect(result.allowed).toBe(false);
62
+ expect(result.retryAfter).toBeDefined();
63
+ });
64
+ it('should track connections separately', () => {
65
+ // conn-1 使用完配额
66
+ for (let i = 0; i < 5; i++) {
67
+ service.checkMessageRate('conn-1');
68
+ }
69
+ // conn-2 应该仍然可用
70
+ const result = service.checkMessageRate('conn-2');
71
+ expect(result.allowed).toBe(true);
72
+ });
73
+ it('should enforce burst limit', () => {
74
+ // 创建一个较大突发限制的服务
75
+ const burstConfig = {
76
+ ...configService,
77
+ messageRateLimitPerConnection: 100,
78
+ messageBurstLimit: 5,
79
+ };
80
+ const burstService = new rate_limiter_service_1.RateLimiterService(burstConfig);
81
+ // 快速发送消息直到突发限制
82
+ for (let i = 0; i < 5; i++) {
83
+ const result = burstService.checkMessageRate(connectionId);
84
+ expect(result.allowed).toBe(true);
85
+ }
86
+ // 下一个消息应该因突发限制被拒绝
87
+ const result = burstService.checkMessageRate(connectionId);
88
+ expect(result.allowed).toBe(false);
89
+ });
90
+ });
91
+ describe('removeConnection', () => {
92
+ it('should clean up connection data', () => {
93
+ const connectionId = 'conn-1';
94
+ // 发送一些消息
95
+ service.checkMessageRate(connectionId);
96
+ // 移除连接
97
+ service.removeConnection(connectionId);
98
+ // 应该不会报错
99
+ expect(() => service.removeConnection(connectionId)).not.toThrow();
100
+ });
101
+ });
102
+ describe('getStats', () => {
103
+ it('should return current statistics', () => {
104
+ // 创建一些活动
105
+ service.checkConnectionRate();
106
+ service.checkConnectionRate();
107
+ service.checkMessageRate('conn-1');
108
+ service.checkMessageRate('conn-2');
109
+ const stats = service.getStats();
110
+ expect(stats.connectionRate).toBe(2);
111
+ expect(stats.globalMessageRate).toBe(2);
112
+ expect(stats.trackedConnections).toBe(2);
113
+ });
114
+ it('should return zero stats initially', () => {
115
+ const stats = service.getStats();
116
+ expect(stats.connectionRate).toBe(0);
117
+ expect(stats.globalMessageRate).toBe(0);
118
+ expect(stats.trackedConnections).toBe(0);
119
+ });
120
+ });
121
+ describe('sliding window behavior', () => {
122
+ it('should slide window and reset old counts', async () => {
123
+ // 发送一些连接
124
+ for (let i = 0; i < 5; i++) {
125
+ service.checkConnectionRate();
126
+ }
127
+ const statsBefore = service.getStats();
128
+ expect(statsBefore.connectionRate).toBe(5);
129
+ // 等待窗口滑动
130
+ await new Promise((resolve) => setTimeout(resolve, 1100));
131
+ // 再检查一次以触发滑动
132
+ service.checkConnectionRate();
133
+ const statsAfter = service.getStats();
134
+ // 旧的计数应该被清除,只剩下最新的1个
135
+ expect(statsAfter.connectionRate).toBeLessThanOrEqual(2);
136
+ });
137
+ });
138
+ });
139
+ //# sourceMappingURL=rate-limiter.service.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.service.spec.js","sourceRoot":"","sources":["../../../test/ratelimit/rate-limiter.service.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../test/setup.ts"],"names":[],"mappings":""}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ /// <reference types="jest" />
37
+ const dotenv = __importStar(require("dotenv"));
38
+ const path = __importStar(require("path"));
39
+ /**
40
+ * Jest 测试环境设置
41
+ */
42
+ // 加载根目录的 .env 文件
43
+ dotenv.config({ path: path.resolve(__dirname, '../../../.env') });
44
+ // 设置测试超时时间
45
+ jest.setTimeout(10000);
46
+ // 模拟环境变量(优先使用已有的环境变量)
47
+ process.env.NODE_ENV = 'test';
48
+ process.env.GATEWAY_ID = process.env.GATEWAY_ID || 'gateway-test';
49
+ process.env.REDIS_HOST = process.env.REDIS_HOST || 'localhost';
50
+ process.env.REDIS_PORT = process.env.REDIS_PORT || '6379';
51
+ // 全局清理
52
+ afterAll(async () => {
53
+ // 确保所有异步操作完成
54
+ await new Promise((resolve) => setTimeout(resolve, 100));
55
+ });
56
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../test/setup.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8BAA8B;AAC9B,+CAAiC;AACjC,2CAA6B;AAE7B;;GAEG;AAEH,iBAAiB;AACjB,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC;AAElE,WAAW;AACX,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAEvB,sBAAsB;AACtB,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC;AAC9B,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,cAAc,CAAC;AAClE,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,WAAW,CAAC;AAC/D,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,MAAM,CAAC;AAE1D,OAAO;AACP,QAAQ,CAAC,KAAK,IAAI,EAAE;IAClB,aAAa;IACb,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;AAC3D,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=message-router.service.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-router.service.spec.d.ts","sourceRoot":"","sources":["../../../test/ws/message-router.service.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,403 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /// <reference types="jest" />
4
+ const message_router_service_1 = require("../../src/ws/message-router.service");
5
+ const core_1 = require("@roomkit/core");
6
+ describe('MessageRouterService', () => {
7
+ let service;
8
+ let configService;
9
+ let redisService;
10
+ let connectionService;
11
+ const mockGatewayId = 'gateway-test-001';
12
+ const mockWorkerId = 'worker-test-001';
13
+ beforeEach(() => {
14
+ // 创建模拟的依赖服务
15
+ configService = {
16
+ gatewayId: mockGatewayId,
17
+ };
18
+ redisService = {
19
+ client: {
20
+ get: jest.fn(),
21
+ setnx: jest.fn(),
22
+ smembers: jest.fn(),
23
+ srandmember: jest.fn(),
24
+ hgetall: jest.fn(),
25
+ set: jest.fn(),
26
+ del: jest.fn(),
27
+ },
28
+ publish: jest.fn().mockResolvedValue(undefined),
29
+ evalScript: jest.fn().mockResolvedValue(null),
30
+ };
31
+ connectionService = {
32
+ touch: jest.fn(),
33
+ send: jest.fn().mockReturnValue(true),
34
+ sendByType: jest.fn().mockReturnValue(true),
35
+ updateStatus: jest.fn(),
36
+ setRoom: jest.fn(),
37
+ getConnection: jest.fn(),
38
+ };
39
+ const sessionService = {
40
+ createOrUpdateSession: jest.fn(),
41
+ getSessionByUserId: jest.fn(),
42
+ getSessionByToken: jest.fn(),
43
+ updateConnectionInfo: jest.fn(),
44
+ addRoomToSession: jest.fn(),
45
+ removeRoomFromSession: jest.fn(),
46
+ };
47
+ service = new message_router_service_1.MessageRouterService(configService, redisService, connectionService, sessionService);
48
+ });
49
+ afterEach(() => {
50
+ jest.clearAllMocks();
51
+ });
52
+ describe('handleMessage - Heartbeat', () => {
53
+ it('should respond to heartbeat directly without forwarding to worker', async () => {
54
+ const connection = {
55
+ id: 'conn-1',
56
+ status: 'identified',
57
+ lastActivity: Date.now(),
58
+ createdAt: Date.now(),
59
+ rooms: new Set(),
60
+ };
61
+ const message = {
62
+ msgType: core_1.MessageType.MSG_HEARTBEAT,
63
+ payload: { timestamp: 1234567890 },
64
+ };
65
+ await service.handleMessage(connection, message);
66
+ // 应该更新活动时间
67
+ expect(connectionService.touch).toHaveBeenCalledWith(connection.id);
68
+ // 应该直接响应心跳
69
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_HEARTBEAT_ACK, expect.objectContaining({
70
+ timestamp: 1234567890,
71
+ serverTime: expect.any(Number),
72
+ }));
73
+ // 不应发布到Redis
74
+ expect(redisService.publish).not.toHaveBeenCalled();
75
+ });
76
+ });
77
+ describe('handleMessage - Auth', () => {
78
+ it('should reject auth request if connection is not in connected state', async () => {
79
+ const connection = {
80
+ id: 'conn-1',
81
+ status: 'identified', // 已认证状态
82
+ lastActivity: Date.now(),
83
+ createdAt: Date.now(),
84
+ rooms: new Set(),
85
+ };
86
+ const message = {
87
+ msgType: core_1.MessageType.MSG_AUTH,
88
+ payload: { token: 'test-token' },
89
+ };
90
+ await service.handleMessage(connection, message);
91
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_AUTH_FAIL, expect.objectContaining({
92
+ success: false,
93
+ error: 'INVALID_STATE',
94
+ }));
95
+ });
96
+ it('should reject auth request with invalid payload', async () => {
97
+ const connection = {
98
+ id: 'conn-1',
99
+ status: 'connected',
100
+ lastActivity: Date.now(),
101
+ createdAt: Date.now(),
102
+ rooms: new Set(),
103
+ };
104
+ const message = {
105
+ msgType: core_1.MessageType.MSG_AUTH,
106
+ payload: {}, // 缺少必需的 token 字段
107
+ };
108
+ await service.handleMessage(connection, message);
109
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_AUTH_FAIL, expect.objectContaining({
110
+ success: false,
111
+ error: 'INVALID_PAYLOAD',
112
+ }));
113
+ });
114
+ it('should forward valid auth request to worker', async () => {
115
+ const connection = {
116
+ id: 'conn-1',
117
+ status: 'connected',
118
+ lastActivity: Date.now(),
119
+ createdAt: Date.now(),
120
+ rooms: new Set(),
121
+ };
122
+ // 模拟有可用的 Worker
123
+ redisService.client.smembers.mockResolvedValue([mockWorkerId]);
124
+ redisService.client.srandmember.mockResolvedValue(mockWorkerId);
125
+ const message = {
126
+ msgType: core_1.MessageType.MSG_AUTH,
127
+ payload: { token: 'valid-token' },
128
+ };
129
+ await service.handleMessage(connection, message);
130
+ // 应该更新状态为 authenticating
131
+ expect(connectionService.updateStatus).toHaveBeenCalledWith(connection.id, 'authenticating');
132
+ // 应该发布消息到 Worker
133
+ expect(redisService.publish).toHaveBeenCalledWith(expect.stringContaining('worker'), expect.objectContaining({
134
+ type: 'auth',
135
+ gatewayId: mockGatewayId,
136
+ connectionId: connection.id,
137
+ msgType: core_1.MessageType.MSG_AUTH,
138
+ }));
139
+ });
140
+ it('should reject auth when no worker available', async () => {
141
+ const connection = {
142
+ id: 'conn-1',
143
+ status: 'connected',
144
+ lastActivity: Date.now(),
145
+ createdAt: Date.now(),
146
+ rooms: new Set(),
147
+ };
148
+ // 模拟没有可用的 Worker
149
+ redisService.client.smembers.mockResolvedValue([]);
150
+ const message = {
151
+ msgType: core_1.MessageType.MSG_AUTH,
152
+ payload: { token: 'valid-token' },
153
+ };
154
+ await service.handleMessage(connection, message);
155
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_AUTH_FAIL, expect.objectContaining({
156
+ success: false,
157
+ error: 'NO_WORKER_AVAILABLE',
158
+ }));
159
+ });
160
+ });
161
+ describe('handleMessage - Unauthenticated access', () => {
162
+ it('should reject non-auth messages from unauthenticated connection', async () => {
163
+ const connection = {
164
+ id: 'conn-1',
165
+ status: 'connected', // 未认证
166
+ lastActivity: Date.now(),
167
+ createdAt: Date.now(),
168
+ rooms: new Set(),
169
+ };
170
+ const message = {
171
+ msgType: core_1.MessageType.MSG_ROOM_CREATE,
172
+ payload: { gameType: 'echo' },
173
+ };
174
+ await service.handleMessage(connection, message);
175
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_ERROR, expect.objectContaining({
176
+ error: 'NOT_AUTHENTICATED',
177
+ }));
178
+ });
179
+ });
180
+ describe('handleMessage - Create Room', () => {
181
+ it('should reject create room with invalid payload', async () => {
182
+ const connection = {
183
+ id: 'conn-1',
184
+ userId: 'user-1',
185
+ status: 'identified',
186
+ lastActivity: Date.now(),
187
+ createdAt: Date.now(),
188
+ rooms: new Set(),
189
+ };
190
+ const message = {
191
+ msgType: core_1.MessageType.MSG_ROOM_CREATE,
192
+ payload: {}, // 缺少 gameType
193
+ };
194
+ await service.handleMessage(connection, message);
195
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_ROOM_CREATE_FAIL, expect.objectContaining({
196
+ success: false,
197
+ error: 'INVALID_PAYLOAD',
198
+ }));
199
+ });
200
+ it('should reject create room when no worker available', async () => {
201
+ const connection = {
202
+ id: 'conn-1',
203
+ userId: 'user-1',
204
+ status: 'identified',
205
+ lastActivity: Date.now(),
206
+ createdAt: Date.now(),
207
+ rooms: new Set(),
208
+ };
209
+ // 模拟没有可用的 Worker
210
+ redisService.client.smembers.mockResolvedValue([]);
211
+ const message = {
212
+ msgType: core_1.MessageType.MSG_ROOM_CREATE,
213
+ payload: { gameType: 'echo', maxPlayers: 10 },
214
+ };
215
+ await service.handleMessage(connection, message);
216
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_ROOM_CREATE_FAIL, expect.objectContaining({
217
+ success: false,
218
+ error: 'NO_WORKER_AVAILABLE',
219
+ }));
220
+ });
221
+ it('should reject duplicate room creation', async () => {
222
+ const connection = {
223
+ id: 'conn-1',
224
+ userId: 'user-1',
225
+ status: 'identified',
226
+ lastActivity: Date.now(),
227
+ createdAt: Date.now(),
228
+ rooms: new Set(),
229
+ };
230
+ redisService.client.smembers.mockResolvedValue([mockWorkerId]);
231
+ redisService.client.srandmember.mockResolvedValue(mockWorkerId);
232
+ // 模拟房间已存在(setnx 返回 0)
233
+ redisService.client.setnx.mockResolvedValue(0);
234
+ const message = {
235
+ msgType: core_1.MessageType.MSG_ROOM_CREATE,
236
+ payload: { roomId: 'existing-room', gameType: 'echo', maxPlayers: 10 },
237
+ };
238
+ await service.handleMessage(connection, message);
239
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_ROOM_CREATE_FAIL, expect.objectContaining({
240
+ success: false,
241
+ error: 'ROOM_ALREADY_EXISTS',
242
+ }));
243
+ });
244
+ it('should forward valid create room request to worker', async () => {
245
+ const connection = {
246
+ id: 'conn-1',
247
+ userId: 'user-1',
248
+ status: 'identified',
249
+ lastActivity: Date.now(),
250
+ createdAt: Date.now(),
251
+ rooms: new Set(),
252
+ };
253
+ redisService.client.smembers.mockResolvedValue([mockWorkerId]);
254
+ redisService.client.srandmember.mockResolvedValue(mockWorkerId);
255
+ // 模拟房间不存在(setnx 返回 1)
256
+ redisService.client.setnx.mockResolvedValue(1);
257
+ const message = {
258
+ msgType: core_1.MessageType.MSG_ROOM_CREATE,
259
+ payload: { gameType: 'echo', maxPlayers: 10, config: {} },
260
+ };
261
+ await service.handleMessage(connection, message);
262
+ expect(redisService.publish).toHaveBeenCalledWith(expect.stringContaining('worker'), expect.objectContaining({
263
+ type: 'client-message',
264
+ msgType: core_1.MessageType.MSG_ROOM_CREATE,
265
+ userId: 'user-1',
266
+ }));
267
+ });
268
+ });
269
+ describe('handleMessage - Join Room', () => {
270
+ it('should reject join room when room not found', async () => {
271
+ const connection = {
272
+ id: 'conn-1',
273
+ userId: 'user-1',
274
+ status: 'identified',
275
+ lastActivity: Date.now(),
276
+ createdAt: Date.now(),
277
+ rooms: new Set(),
278
+ };
279
+ // 模拟房间不存在
280
+ redisService.client.get.mockResolvedValue(null);
281
+ const message = {
282
+ msgType: core_1.MessageType.MSG_ROOM_JOIN,
283
+ payload: { roomId: 'non-existent-room' },
284
+ };
285
+ await service.handleMessage(connection, message);
286
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_ROOM_JOIN_FAIL, expect.objectContaining({
287
+ success: false,
288
+ error: 'ROOM_NOT_FOUND',
289
+ }));
290
+ });
291
+ it('should forward valid join room request to worker', async () => {
292
+ const connection = {
293
+ id: 'conn-1',
294
+ userId: 'user-1',
295
+ status: 'identified',
296
+ lastActivity: Date.now(),
297
+ createdAt: Date.now(),
298
+ rooms: new Set(),
299
+ };
300
+ // 模拟房间存在
301
+ redisService.client.get.mockResolvedValue(mockWorkerId);
302
+ const message = {
303
+ msgType: core_1.MessageType.MSG_ROOM_JOIN,
304
+ payload: { roomId: 'room-123' },
305
+ };
306
+ await service.handleMessage(connection, message);
307
+ expect(redisService.publish).toHaveBeenCalledWith(expect.stringContaining('worker'), expect.objectContaining({
308
+ type: 'client-message',
309
+ msgType: core_1.MessageType.MSG_ROOM_JOIN,
310
+ roomId: 'room-123',
311
+ }));
312
+ });
313
+ });
314
+ describe('handleMessage - Leave Room', () => {
315
+ it('should reject leave room when not in room', async () => {
316
+ const connection = {
317
+ id: 'conn-1',
318
+ userId: 'user-1',
319
+ status: 'identified',
320
+ currentRoom: undefined, // 不在房间中
321
+ lastActivity: Date.now(),
322
+ createdAt: Date.now(),
323
+ rooms: new Set(),
324
+ };
325
+ const message = {
326
+ msgType: core_1.MessageType.MSG_ROOM_LEAVE,
327
+ payload: {},
328
+ };
329
+ await service.handleMessage(connection, message);
330
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_ERROR, expect.objectContaining({
331
+ success: false,
332
+ error: 'NOT_IN_ROOM',
333
+ }));
334
+ });
335
+ it('should forward leave room request to worker', async () => {
336
+ const connection = {
337
+ id: 'conn-1',
338
+ userId: 'user-1',
339
+ status: 'in-room',
340
+ currentRoom: 'room-123',
341
+ lastActivity: Date.now(),
342
+ createdAt: Date.now(),
343
+ rooms: new Set(),
344
+ };
345
+ redisService.client.get.mockResolvedValue(mockWorkerId);
346
+ const message = {
347
+ msgType: core_1.MessageType.MSG_ROOM_LEAVE,
348
+ payload: {},
349
+ };
350
+ await service.handleMessage(connection, message);
351
+ expect(redisService.publish).toHaveBeenCalledWith(expect.stringContaining('worker'), expect.objectContaining({
352
+ type: 'client-message',
353
+ msgType: core_1.MessageType.MSG_ROOM_LEAVE,
354
+ roomId: 'room-123',
355
+ }));
356
+ });
357
+ });
358
+ describe('handleMessage - Game Logic', () => {
359
+ it('should reject game message when not in room', async () => {
360
+ const connection = {
361
+ id: 'conn-1',
362
+ userId: 'user-1',
363
+ status: 'identified',
364
+ currentRoom: undefined,
365
+ lastActivity: Date.now(),
366
+ createdAt: Date.now(),
367
+ rooms: new Set(),
368
+ };
369
+ const message = {
370
+ msgType: 'chat',
371
+ payload: { message: 'Hello!' },
372
+ };
373
+ await service.handleMessage(connection, message);
374
+ expect(connectionService.sendByType).toHaveBeenCalledWith(connection.id, core_1.MessageType.MSG_ERROR, expect.objectContaining({
375
+ error: 'NOT_IN_ROOM',
376
+ }));
377
+ });
378
+ it('should forward game message to worker when in room', async () => {
379
+ const connection = {
380
+ id: 'conn-1',
381
+ userId: 'user-1',
382
+ status: 'in-room',
383
+ currentRoom: 'room-123',
384
+ lastActivity: Date.now(),
385
+ createdAt: Date.now(),
386
+ rooms: new Set(),
387
+ };
388
+ redisService.client.get.mockResolvedValue(mockWorkerId);
389
+ const message = {
390
+ msgType: 'chat',
391
+ payload: { message: 'Hello!' },
392
+ };
393
+ await service.handleMessage(connection, message);
394
+ expect(redisService.publish).toHaveBeenCalledWith(expect.stringContaining('worker'), expect.objectContaining({
395
+ type: 'client-message',
396
+ msgType: 'chat',
397
+ userId: 'user-1',
398
+ roomId: 'room-123',
399
+ }));
400
+ });
401
+ });
402
+ });
403
+ //# sourceMappingURL=message-router.service.spec.js.map