servcraft 0.1.0 → 0.1.3

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 (217) hide show
  1. package/.claude/settings.local.json +30 -0
  2. package/.github/CODEOWNERS +18 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +46 -0
  4. package/.github/dependabot.yml +59 -0
  5. package/.github/workflows/ci.yml +188 -0
  6. package/.github/workflows/release.yml +195 -0
  7. package/AUDIT.md +602 -0
  8. package/LICENSE +21 -0
  9. package/README.md +1102 -1
  10. package/dist/cli/index.cjs +2026 -2168
  11. package/dist/cli/index.cjs.map +1 -1
  12. package/dist/cli/index.js +2026 -2168
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/index.cjs +595 -616
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +114 -52
  17. package/dist/index.d.ts +114 -52
  18. package/dist/index.js +595 -616
  19. package/dist/index.js.map +1 -1
  20. package/docs/CLI-001_MULTI_DB_PLAN.md +546 -0
  21. package/docs/DATABASE_MULTI_ORM.md +399 -0
  22. package/docs/PHASE1_BREAKDOWN.md +346 -0
  23. package/docs/PROGRESS.md +550 -0
  24. package/docs/modules/ANALYTICS.md +226 -0
  25. package/docs/modules/API-VERSIONING.md +252 -0
  26. package/docs/modules/AUDIT.md +192 -0
  27. package/docs/modules/AUTH.md +431 -0
  28. package/docs/modules/CACHE.md +346 -0
  29. package/docs/modules/EMAIL.md +254 -0
  30. package/docs/modules/FEATURE-FLAG.md +291 -0
  31. package/docs/modules/I18N.md +294 -0
  32. package/docs/modules/MEDIA-PROCESSING.md +281 -0
  33. package/docs/modules/MFA.md +266 -0
  34. package/docs/modules/NOTIFICATION.md +311 -0
  35. package/docs/modules/OAUTH.md +237 -0
  36. package/docs/modules/PAYMENT.md +804 -0
  37. package/docs/modules/QUEUE.md +540 -0
  38. package/docs/modules/RATE-LIMIT.md +339 -0
  39. package/docs/modules/SEARCH.md +288 -0
  40. package/docs/modules/SECURITY.md +327 -0
  41. package/docs/modules/SESSION.md +382 -0
  42. package/docs/modules/SWAGGER.md +305 -0
  43. package/docs/modules/UPLOAD.md +296 -0
  44. package/docs/modules/USER.md +505 -0
  45. package/docs/modules/VALIDATION.md +294 -0
  46. package/docs/modules/WEBHOOK.md +270 -0
  47. package/docs/modules/WEBSOCKET.md +691 -0
  48. package/package.json +53 -38
  49. package/prisma/schema.prisma +395 -1
  50. package/src/cli/commands/add-module.ts +520 -87
  51. package/src/cli/commands/db.ts +3 -4
  52. package/src/cli/commands/docs.ts +256 -6
  53. package/src/cli/commands/generate.ts +12 -19
  54. package/src/cli/commands/init.ts +384 -214
  55. package/src/cli/index.ts +0 -4
  56. package/src/cli/templates/repository.ts +6 -1
  57. package/src/cli/templates/routes.ts +6 -21
  58. package/src/cli/utils/docs-generator.ts +6 -7
  59. package/src/cli/utils/env-manager.ts +717 -0
  60. package/src/cli/utils/field-parser.ts +16 -7
  61. package/src/cli/utils/interactive-prompt.ts +223 -0
  62. package/src/cli/utils/template-manager.ts +346 -0
  63. package/src/config/database.config.ts +183 -0
  64. package/src/config/env.ts +0 -10
  65. package/src/config/index.ts +0 -14
  66. package/src/core/server.ts +1 -1
  67. package/src/database/adapters/mongoose.adapter.ts +132 -0
  68. package/src/database/adapters/prisma.adapter.ts +118 -0
  69. package/src/database/connection.ts +190 -0
  70. package/src/database/interfaces/database.interface.ts +85 -0
  71. package/src/database/interfaces/index.ts +7 -0
  72. package/src/database/interfaces/repository.interface.ts +129 -0
  73. package/src/database/models/mongoose/index.ts +7 -0
  74. package/src/database/models/mongoose/payment.schema.ts +347 -0
  75. package/src/database/models/mongoose/user.schema.ts +154 -0
  76. package/src/database/prisma.ts +1 -4
  77. package/src/database/redis.ts +101 -0
  78. package/src/database/repositories/mongoose/index.ts +7 -0
  79. package/src/database/repositories/mongoose/payment.repository.ts +380 -0
  80. package/src/database/repositories/mongoose/user.repository.ts +255 -0
  81. package/src/database/seed.ts +6 -1
  82. package/src/index.ts +9 -20
  83. package/src/middleware/security.ts +2 -6
  84. package/src/modules/analytics/analytics.routes.ts +80 -0
  85. package/src/modules/analytics/analytics.service.ts +364 -0
  86. package/src/modules/analytics/index.ts +18 -0
  87. package/src/modules/analytics/types.ts +180 -0
  88. package/src/modules/api-versioning/index.ts +15 -0
  89. package/src/modules/api-versioning/types.ts +86 -0
  90. package/src/modules/api-versioning/versioning.middleware.ts +120 -0
  91. package/src/modules/api-versioning/versioning.routes.ts +54 -0
  92. package/src/modules/api-versioning/versioning.service.ts +189 -0
  93. package/src/modules/audit/audit.repository.ts +206 -0
  94. package/src/modules/audit/audit.service.ts +27 -59
  95. package/src/modules/auth/auth.controller.ts +2 -2
  96. package/src/modules/auth/auth.middleware.ts +3 -9
  97. package/src/modules/auth/auth.routes.ts +10 -107
  98. package/src/modules/auth/auth.service.ts +126 -23
  99. package/src/modules/auth/index.ts +3 -4
  100. package/src/modules/cache/cache.service.ts +367 -0
  101. package/src/modules/cache/index.ts +10 -0
  102. package/src/modules/cache/types.ts +44 -0
  103. package/src/modules/email/email.service.ts +3 -10
  104. package/src/modules/email/templates.ts +2 -8
  105. package/src/modules/feature-flag/feature-flag.repository.ts +303 -0
  106. package/src/modules/feature-flag/feature-flag.routes.ts +247 -0
  107. package/src/modules/feature-flag/feature-flag.service.ts +566 -0
  108. package/src/modules/feature-flag/index.ts +20 -0
  109. package/src/modules/feature-flag/types.ts +192 -0
  110. package/src/modules/i18n/i18n.middleware.ts +186 -0
  111. package/src/modules/i18n/i18n.routes.ts +191 -0
  112. package/src/modules/i18n/i18n.service.ts +456 -0
  113. package/src/modules/i18n/index.ts +18 -0
  114. package/src/modules/i18n/types.ts +118 -0
  115. package/src/modules/media-processing/index.ts +17 -0
  116. package/src/modules/media-processing/media-processing.routes.ts +111 -0
  117. package/src/modules/media-processing/media-processing.service.ts +245 -0
  118. package/src/modules/media-processing/types.ts +156 -0
  119. package/src/modules/mfa/index.ts +20 -0
  120. package/src/modules/mfa/mfa.repository.ts +206 -0
  121. package/src/modules/mfa/mfa.routes.ts +595 -0
  122. package/src/modules/mfa/mfa.service.ts +572 -0
  123. package/src/modules/mfa/totp.ts +150 -0
  124. package/src/modules/mfa/types.ts +57 -0
  125. package/src/modules/notification/index.ts +20 -0
  126. package/src/modules/notification/notification.repository.ts +356 -0
  127. package/src/modules/notification/notification.service.ts +483 -0
  128. package/src/modules/notification/types.ts +119 -0
  129. package/src/modules/oauth/index.ts +20 -0
  130. package/src/modules/oauth/oauth.repository.ts +219 -0
  131. package/src/modules/oauth/oauth.routes.ts +446 -0
  132. package/src/modules/oauth/oauth.service.ts +293 -0
  133. package/src/modules/oauth/providers/apple.provider.ts +250 -0
  134. package/src/modules/oauth/providers/facebook.provider.ts +181 -0
  135. package/src/modules/oauth/providers/github.provider.ts +248 -0
  136. package/src/modules/oauth/providers/google.provider.ts +189 -0
  137. package/src/modules/oauth/providers/twitter.provider.ts +214 -0
  138. package/src/modules/oauth/types.ts +94 -0
  139. package/src/modules/payment/index.ts +19 -0
  140. package/src/modules/payment/payment.repository.ts +733 -0
  141. package/src/modules/payment/payment.routes.ts +390 -0
  142. package/src/modules/payment/payment.service.ts +354 -0
  143. package/src/modules/payment/providers/mobile-money.provider.ts +274 -0
  144. package/src/modules/payment/providers/paypal.provider.ts +190 -0
  145. package/src/modules/payment/providers/stripe.provider.ts +215 -0
  146. package/src/modules/payment/types.ts +140 -0
  147. package/src/modules/queue/cron.ts +438 -0
  148. package/src/modules/queue/index.ts +87 -0
  149. package/src/modules/queue/queue.routes.ts +600 -0
  150. package/src/modules/queue/queue.service.ts +842 -0
  151. package/src/modules/queue/types.ts +222 -0
  152. package/src/modules/queue/workers.ts +366 -0
  153. package/src/modules/rate-limit/index.ts +59 -0
  154. package/src/modules/rate-limit/rate-limit.middleware.ts +134 -0
  155. package/src/modules/rate-limit/rate-limit.routes.ts +269 -0
  156. package/src/modules/rate-limit/rate-limit.service.ts +348 -0
  157. package/src/modules/rate-limit/stores/memory.store.ts +165 -0
  158. package/src/modules/rate-limit/stores/redis.store.ts +322 -0
  159. package/src/modules/rate-limit/types.ts +153 -0
  160. package/src/modules/search/adapters/elasticsearch.adapter.ts +326 -0
  161. package/src/modules/search/adapters/meilisearch.adapter.ts +261 -0
  162. package/src/modules/search/adapters/memory.adapter.ts +278 -0
  163. package/src/modules/search/index.ts +21 -0
  164. package/src/modules/search/search.service.ts +234 -0
  165. package/src/modules/search/types.ts +214 -0
  166. package/src/modules/security/index.ts +40 -0
  167. package/src/modules/security/sanitize.ts +223 -0
  168. package/src/modules/security/security-audit.service.ts +388 -0
  169. package/src/modules/security/security.middleware.ts +398 -0
  170. package/src/modules/session/index.ts +3 -0
  171. package/src/modules/session/session.repository.ts +159 -0
  172. package/src/modules/session/session.service.ts +340 -0
  173. package/src/modules/session/types.ts +38 -0
  174. package/src/modules/swagger/index.ts +7 -1
  175. package/src/modules/swagger/schema-builder.ts +16 -4
  176. package/src/modules/swagger/swagger.service.ts +9 -10
  177. package/src/modules/swagger/types.ts +0 -2
  178. package/src/modules/upload/index.ts +14 -0
  179. package/src/modules/upload/types.ts +83 -0
  180. package/src/modules/upload/upload.repository.ts +199 -0
  181. package/src/modules/upload/upload.routes.ts +311 -0
  182. package/src/modules/upload/upload.service.ts +448 -0
  183. package/src/modules/user/index.ts +3 -3
  184. package/src/modules/user/user.controller.ts +15 -9
  185. package/src/modules/user/user.repository.ts +237 -113
  186. package/src/modules/user/user.routes.ts +39 -164
  187. package/src/modules/user/user.service.ts +4 -3
  188. package/src/modules/validation/validator.ts +12 -17
  189. package/src/modules/webhook/index.ts +91 -0
  190. package/src/modules/webhook/retry.ts +196 -0
  191. package/src/modules/webhook/signature.ts +135 -0
  192. package/src/modules/webhook/types.ts +181 -0
  193. package/src/modules/webhook/webhook.repository.ts +358 -0
  194. package/src/modules/webhook/webhook.routes.ts +442 -0
  195. package/src/modules/webhook/webhook.service.ts +457 -0
  196. package/src/modules/websocket/features.ts +504 -0
  197. package/src/modules/websocket/index.ts +106 -0
  198. package/src/modules/websocket/middlewares.ts +298 -0
  199. package/src/modules/websocket/types.ts +181 -0
  200. package/src/modules/websocket/websocket.service.ts +692 -0
  201. package/src/utils/errors.ts +7 -0
  202. package/src/utils/pagination.ts +4 -1
  203. package/tests/helpers/db-check.ts +79 -0
  204. package/tests/integration/auth-redis.test.ts +94 -0
  205. package/tests/integration/cache-redis.test.ts +387 -0
  206. package/tests/integration/mongoose-repositories.test.ts +410 -0
  207. package/tests/integration/payment-prisma.test.ts +637 -0
  208. package/tests/integration/queue-bullmq.test.ts +417 -0
  209. package/tests/integration/user-prisma.test.ts +441 -0
  210. package/tests/integration/websocket-socketio.test.ts +552 -0
  211. package/tests/setup.ts +11 -9
  212. package/vitest.config.ts +3 -8
  213. package/npm-cache/_cacache/content-v2/sha512/1c/d0/03440d500a0487621aad1d6402978340698976602046db8e24fa03c01ee6c022c69b0582f969042d9442ee876ac35c038e960dd427d1e622fa24b8eb7dba +0 -0
  214. package/npm-cache/_cacache/content-v2/sha512/42/55/28b493ca491833e5aab0e9c3108d29ab3f36c248ca88f45d4630674fce9130959e56ae308797ac2b6328fa7f09a610b9550ed09cb971d039876d293fc69d +0 -0
  215. package/npm-cache/_cacache/content-v2/sha512/e0/12/f360dc9315ee5f17844a0c8c233ee6bf7c30837c4a02ea0d56c61c7f7ab21c0e958e50ed2c57c59f983c762b93056778c9009b2398ffc26def0183999b13 +0 -0
  216. package/npm-cache/_cacache/content-v2/sha512/ed/b0/fae1161902898f4c913c67d7f6cdf6be0665aec3b389b9c4f4f0a101ca1da59badf1b59c4e0030f5223023b8d63cfe501c46a32c20c895d4fb3f11ca2232 +0 -0
  217. package/npm-cache/_cacache/index-v5/58/94/c2cba79e0f16b4c10e95a87e32255741149e8222cc314a476aab67c39cc0 +0 -5
@@ -0,0 +1,691 @@
1
+ # WebSocket Module Documentation
2
+
3
+ ## Overview
4
+
5
+ The WebSocket module provides real-time bidirectional communication using Socket.io with Redis adapter support for multi-instance deployments. It manages connections, rooms, messages, and broadcasting capabilities.
6
+
7
+ ## Features
8
+
9
+ - ✅ Real Socket.io integration (HTTP server required)
10
+ - ✅ Redis adapter for multi-instance support
11
+ - ✅ Connection lifecycle management
12
+ - ✅ Room-based communication
13
+ - ✅ Message history storage
14
+ - ✅ Broadcasting (to rooms, users, all)
15
+ - ✅ Typing indicators
16
+ - ✅ User presence tracking
17
+ - ✅ Connection statistics
18
+ - ✅ Graceful shutdown
19
+
20
+ ## Configuration
21
+
22
+ ### Basic Setup (Single Instance)
23
+
24
+ ```typescript
25
+ import { createServer } from 'http';
26
+ import { WebSocketService } from './modules/websocket/websocket.service.js';
27
+
28
+ const httpServer = createServer();
29
+
30
+ const wsService = new WebSocketService({
31
+ path: '/socket.io',
32
+ cors: {
33
+ origin: '*',
34
+ credentials: true,
35
+ },
36
+ pingTimeout: 60000,
37
+ pingInterval: 25000,
38
+ maxHttpBufferSize: 1e6, // 1MB
39
+ });
40
+
41
+ // Initialize Socket.io with HTTP server
42
+ wsService.initialize(httpServer);
43
+
44
+ httpServer.listen(3000);
45
+ ```
46
+
47
+ ### Multi-Instance Setup (with Redis)
48
+
49
+ ```typescript
50
+ const wsService = new WebSocketService({
51
+ path: '/socket.io',
52
+ cors: {
53
+ origin: ['https://example.com', 'https://www.example.com'],
54
+ credentials: true,
55
+ },
56
+ redis: {
57
+ host: process.env.REDIS_HOST || 'localhost',
58
+ port: parseInt(process.env.REDIS_PORT || '6379'),
59
+ password: process.env.REDIS_PASSWORD,
60
+ },
61
+ pingTimeout: 60000,
62
+ pingInterval: 25000,
63
+ });
64
+
65
+ wsService.initialize(httpServer);
66
+ ```
67
+
68
+ ## API Reference
69
+
70
+ ### Initialization
71
+
72
+ #### `initialize(httpServer: HTTPServer): void`
73
+
74
+ Initialize Socket.io server with an HTTP server instance.
75
+
76
+ ```typescript
77
+ wsService.initialize(httpServer);
78
+ ```
79
+
80
+ **Important**: Without an HTTP server, the service runs in mock mode (logs only).
81
+
82
+ ### Connection Management
83
+
84
+ #### `handleConnection(socket: AuthenticatedSocket): Promise<void>`
85
+
86
+ Handle new client connection. Called automatically by Socket.io.
87
+
88
+ ```typescript
89
+ // Automatically handled on 'connection' event
90
+ ```
91
+
92
+ #### `handleDisconnection(socketId: string, reason?: string): Promise<void>`
93
+
94
+ Handle client disconnection.
95
+
96
+ ```typescript
97
+ await wsService.handleDisconnection(socketId, 'client_disconnect');
98
+ ```
99
+
100
+ #### `getUser(socketId: string): SocketUser | undefined`
101
+
102
+ Get connected user by socket ID.
103
+
104
+ ```typescript
105
+ const user = wsService.getUser(socketId);
106
+ if (user) {
107
+ console.log(user.username, user.email);
108
+ }
109
+ ```
110
+
111
+ #### `getConnectedUsers(): SocketUser[]`
112
+
113
+ Get all connected users.
114
+
115
+ ```typescript
116
+ const users = wsService.getConnectedUsers();
117
+ console.log(`${users.length} users online`);
118
+ ```
119
+
120
+ #### `isUserOnline(userId: string): boolean`
121
+
122
+ Check if user is online.
123
+
124
+ ```typescript
125
+ if (wsService.isUserOnline(userId)) {
126
+ console.log('User is online');
127
+ }
128
+ ```
129
+
130
+ #### `getUserSockets(userId: string): string[]`
131
+
132
+ Get all socket IDs for a user (multiple tabs/devices).
133
+
134
+ ```typescript
135
+ const sockets = wsService.getUserSockets(userId);
136
+ console.log(`User has ${sockets.length} active connections`);
137
+ ```
138
+
139
+ ### Room Management
140
+
141
+ #### `createRoom(name: string, namespace?: string, createdBy?: string, metadata?: object): Promise<Room>`
142
+
143
+ Create a new room.
144
+
145
+ ```typescript
146
+ const room = await wsService.createRoom('general-chat', 'default', userId, {
147
+ topic: 'General Discussion',
148
+ public: true,
149
+ });
150
+ ```
151
+
152
+ #### `getRoom(roomId: string): Room | undefined`
153
+
154
+ Get room by ID.
155
+
156
+ ```typescript
157
+ const room = wsService.getRoom(roomId);
158
+ if (room) {
159
+ console.log(room.name, room.members.size);
160
+ }
161
+ ```
162
+
163
+ #### `listRooms(namespace?: string): Room[]`
164
+
165
+ List all rooms, optionally filtered by namespace.
166
+
167
+ ```typescript
168
+ const allRooms = wsService.listRooms();
169
+ const chatRooms = wsService.listRooms('chat');
170
+ ```
171
+
172
+ #### `joinRoom(socketId: string, roomId: string): Promise<void>`
173
+
174
+ Add user to room.
175
+
176
+ ```typescript
177
+ await wsService.joinRoom(socketId, roomId);
178
+ ```
179
+
180
+ **Note**: Client should also call `socket.join(roomId)` on Socket.io side.
181
+
182
+ #### `leaveRoom(socketId: string, roomId: string): Promise<void>`
183
+
184
+ Remove user from room.
185
+
186
+ ```typescript
187
+ await wsService.leaveRoom(socketId, roomId);
188
+ ```
189
+
190
+ #### `deleteRoom(roomId: string): Promise<void>`
191
+
192
+ Delete a room.
193
+
194
+ ```typescript
195
+ await wsService.deleteRoom(roomId);
196
+ ```
197
+
198
+ #### `getRoomMembers(roomId: string): SocketUser[]`
199
+
200
+ Get all members in a room.
201
+
202
+ ```typescript
203
+ const members = wsService.getRoomMembers(roomId);
204
+ members.forEach((user) => console.log(user.username));
205
+ ```
206
+
207
+ ### Messaging
208
+
209
+ #### `sendMessage(roomId: string, userId: string, content: string, type?: MessageType, metadata?: object): Promise<Message>`
210
+
211
+ Send message to room and store in history.
212
+
213
+ ```typescript
214
+ const message = await wsService.sendMessage(
215
+ roomId,
216
+ userId,
217
+ 'Hello everyone!',
218
+ 'text',
219
+ { edited: false }
220
+ );
221
+ ```
222
+
223
+ **Message types**: `'text'`, `'image'`, `'file'`, `'system'`
224
+
225
+ #### `getRoomMessages(roomId: string, limit?: number, offset?: number): Message[]`
226
+
227
+ Get room message history.
228
+
229
+ ```typescript
230
+ const recentMessages = wsService.getRoomMessages(roomId, 50); // Last 50 messages
231
+ const older = wsService.getRoomMessages(roomId, 50, 50); // 50 messages, skip last 50
232
+ ```
233
+
234
+ ### Broadcasting
235
+
236
+ #### `broadcastToRoom(roomId: string, event: string, data: unknown, options?: BroadcastOptions): Promise<void>`
237
+
238
+ Broadcast event to all users in a room.
239
+
240
+ ```typescript
241
+ await wsService.broadcastToRoom('room-123', 'user:joined', {
242
+ username: 'Alice',
243
+ timestamp: new Date(),
244
+ });
245
+
246
+ // Exclude specific sockets
247
+ await wsService.broadcastToRoom('room-123', 'message', messageData, {
248
+ except: [senderSocketId],
249
+ });
250
+ ```
251
+
252
+ #### `broadcastToUsers(userIds: string[], event: string, data: unknown): Promise<void>`
253
+
254
+ Broadcast to specific users (all their sockets).
255
+
256
+ ```typescript
257
+ await wsService.broadcastToUsers(
258
+ [userId1, userId2, userId3],
259
+ 'notification',
260
+ { type: 'friend_request', from: 'Alice' }
261
+ );
262
+ ```
263
+
264
+ #### `broadcastToAll(event: string, data: unknown, options?: BroadcastOptions): Promise<void>`
265
+
266
+ Broadcast to all connected users.
267
+
268
+ ```typescript
269
+ await wsService.broadcastToAll('system:announcement', {
270
+ message: 'Server maintenance in 5 minutes',
271
+ });
272
+
273
+ // Exclude certain sockets
274
+ await wsService.broadcastToAll('update', data, {
275
+ except: [adminSocketId],
276
+ });
277
+ ```
278
+
279
+ #### `emitToSocket(socketId: string, event: string, data: unknown): Promise<void>`
280
+
281
+ Emit event to specific socket.
282
+
283
+ ```typescript
284
+ await wsService.emitToSocket(socketId, 'private:message', {
285
+ from: 'Admin',
286
+ content: 'Welcome!',
287
+ });
288
+ ```
289
+
290
+ ### Statistics
291
+
292
+ #### `getStats(): ConnectionStats`
293
+
294
+ Get connection statistics.
295
+
296
+ ```typescript
297
+ const stats = wsService.getStats();
298
+ console.log(`
299
+ Total connections: ${stats.totalConnections}
300
+ Active connections: ${stats.activeConnections}
301
+ Total rooms: ${stats.totalRooms}
302
+ `);
303
+ ```
304
+
305
+ #### `getRoomStats(roomId: string): RoomStats | null`
306
+
307
+ Get room statistics.
308
+
309
+ ```typescript
310
+ const stats = wsService.getRoomStats(roomId);
311
+ if (stats) {
312
+ console.log(`
313
+ Members: ${stats.memberCount}
314
+ Messages: ${stats.messageCount}
315
+ Created: ${stats.createdAt}
316
+ Last activity: ${stats.lastActivity}
317
+ `);
318
+ }
319
+ ```
320
+
321
+ ### Maintenance
322
+
323
+ #### `disconnectUser(userId: string, reason?: string): Promise<void>`
324
+
325
+ Forcefully disconnect all user's sockets.
326
+
327
+ ```typescript
328
+ await wsService.disconnectUser(userId, 'violation_of_terms');
329
+ ```
330
+
331
+ #### `cleanup(inactiveMinutes?: number): Promise<number>`
332
+
333
+ Clean up inactive connections.
334
+
335
+ ```typescript
336
+ const cleaned = await wsService.cleanup(30); // Remove connections inactive for 30+ minutes
337
+ console.log(`Cleaned ${cleaned} inactive connections`);
338
+ ```
339
+
340
+ #### `shutdown(): Promise<void>`
341
+
342
+ Gracefully shutdown WebSocket service.
343
+
344
+ ```typescript
345
+ await wsService.shutdown();
346
+ ```
347
+
348
+ ## Client-Side Usage
349
+
350
+ ### Connection
351
+
352
+ ```typescript
353
+ import { io } from 'socket.io-client';
354
+
355
+ const socket = io('http://localhost:3000', {
356
+ path: '/socket.io',
357
+ query: {
358
+ username: 'Alice',
359
+ email: 'alice@example.com',
360
+ },
361
+ });
362
+
363
+ socket.on('connect', () => {
364
+ console.log('Connected:', socket.id);
365
+ });
366
+
367
+ socket.on('disconnect', () => {
368
+ console.log('Disconnected');
369
+ });
370
+ ```
371
+
372
+ ### Joining Rooms
373
+
374
+ ```typescript
375
+ socket.emit('room:join', { roomId: 'room-123' });
376
+
377
+ socket.on('error', (error) => {
378
+ console.error('Error:', error.message);
379
+ });
380
+ ```
381
+
382
+ ### Sending Messages
383
+
384
+ ```typescript
385
+ socket.emit('message', {
386
+ roomId: 'room-123',
387
+ content: 'Hello everyone!',
388
+ type: 'text',
389
+ });
390
+
391
+ socket.on('message', (message) => {
392
+ console.log(`${message.username}: ${message.content}`);
393
+ });
394
+ ```
395
+
396
+ ### Typing Indicators
397
+
398
+ ```typescript
399
+ // Start typing
400
+ socket.emit('typing', { roomId: 'room-123', isTyping: true });
401
+
402
+ // Stop typing
403
+ socket.emit('typing', { roomId: 'room-123', isTyping: false });
404
+
405
+ // Listen for others typing
406
+ socket.on('typing', (data) => {
407
+ if (data.isTyping) {
408
+ console.log(`${data.username} is typing...`);
409
+ } else {
410
+ console.log(`${data.username} stopped typing`);
411
+ }
412
+ });
413
+ ```
414
+
415
+ ### Listening to Events
416
+
417
+ ```typescript
418
+ // Room events
419
+ socket.on('user:joined', (data) => {
420
+ console.log(`${data.username} joined the room`);
421
+ });
422
+
423
+ socket.on('user:left', (data) => {
424
+ console.log(`${data.username} left the room`);
425
+ });
426
+
427
+ // Notifications
428
+ socket.on('notification', (notification) => {
429
+ console.log('New notification:', notification);
430
+ });
431
+
432
+ // System announcements
433
+ socket.on('system:announcement', (data) => {
434
+ alert(data.message);
435
+ });
436
+ ```
437
+
438
+ ## Server-Side Events
439
+
440
+ The WebSocket service emits events via EventEmitter:
441
+
442
+ ```typescript
443
+ wsService.on('connection', (user) => {
444
+ console.log(`User connected: ${user.username}`);
445
+ });
446
+
447
+ wsService.on('disconnect', (user, reason) => {
448
+ console.log(`User disconnected: ${user.username} (${reason})`);
449
+ });
450
+
451
+ wsService.on('message', (message) => {
452
+ console.log(`Message in ${message.roomId}: ${message.content}`);
453
+ });
454
+
455
+ wsService.on('room:join', ({ user, room }) => {
456
+ console.log(`${user.username} joined ${room.name}`);
457
+ });
458
+
459
+ wsService.on('room:leave', ({ user, room }) => {
460
+ console.log(`${user.username} left ${room.name}`);
461
+ });
462
+ ```
463
+
464
+ ## Architecture
465
+
466
+ ### Single Instance
467
+
468
+ ```
469
+ Client <--> Socket.io Server <--> WebSocketService
470
+ |
471
+ In-Memory Storage
472
+ ```
473
+
474
+ ### Multi-Instance (with Redis)
475
+
476
+ ```
477
+ Client 1 <--> Socket.io Server 1 <--\
478
+ |
479
+ Client 2 <--> Socket.io Server 2 <--+-> Redis Pub/Sub <-> WebSocketService
480
+ |
481
+ Client 3 <--> Socket.io Server 3 <--/
482
+ |
483
+ In-Memory Storage (per instance)
484
+ ```
485
+
486
+ ## Use Cases
487
+
488
+ ### Chat Application
489
+
490
+ ```typescript
491
+ // Server
492
+ const chatRoom = await wsService.createRoom('chat-general', 'chat');
493
+
494
+ // Client joins
495
+ socket.emit('room:join', { roomId: chatRoom.id });
496
+
497
+ // Send message
498
+ socket.emit('message', {
499
+ roomId: chatRoom.id,
500
+ content: 'Hello chat!',
501
+ type: 'text',
502
+ });
503
+
504
+ // Everyone in room receives
505
+ socket.on('message', (msg) => {
506
+ displayMessage(msg);
507
+ });
508
+ ```
509
+
510
+ ### Real-Time Notifications
511
+
512
+ ```typescript
513
+ // Server: Send notification to specific user
514
+ await wsService.broadcastToUsers([userId], 'notification', {
515
+ type: 'friend_request',
516
+ from: 'Alice',
517
+ timestamp: new Date(),
518
+ });
519
+
520
+ // Client
521
+ socket.on('notification', (notification) => {
522
+ showNotification(notification);
523
+ });
524
+ ```
525
+
526
+ ### Live Presence
527
+
528
+ ```typescript
529
+ // Track user status
530
+ socket.on('user:status', (data) => {
531
+ updateUserPresence(data.userId, data.status); // online, away, offline
532
+ });
533
+
534
+ // Server broadcast status changes
535
+ await wsService.broadcastToAll('user:status', {
536
+ userId: user.id,
537
+ status: 'online',
538
+ });
539
+ ```
540
+
541
+ ### Collaborative Editing
542
+
543
+ ```typescript
544
+ // Broadcast changes to room
545
+ socket.emit('document:edit', {
546
+ roomId: documentId,
547
+ changes: delta,
548
+ cursor: cursorPosition,
549
+ });
550
+
551
+ // Receive others' changes
552
+ socket.on('document:edit', (data) => {
553
+ applyChanges(data.changes);
554
+ updateCursor(data.userId, data.cursor);
555
+ });
556
+ ```
557
+
558
+ ## Environment Variables
559
+
560
+ ```bash
561
+ # Redis Configuration (for multi-instance)
562
+ REDIS_HOST=localhost
563
+ REDIS_PORT=6379
564
+ REDIS_PASSWORD=your_redis_password
565
+
566
+ # Socket.io Configuration
567
+ WEBSOCKET_PATH=/socket.io
568
+ WEBSOCKET_PING_TIMEOUT=60000
569
+ WEBSOCKET_PING_INTERVAL=25000
570
+ ```
571
+
572
+ ## Migration from Mock Implementation
573
+
574
+ **Before (v0.1.0):**
575
+ ```typescript
576
+ // Placeholder Socket.io - not actually connected
577
+ wsService.initialize(); // No HTTP server needed
578
+ // Broadcasts only logged, not actually sent
579
+ ```
580
+
581
+ **After (v0.2.0):**
582
+ ```typescript
583
+ // Real Socket.io connection
584
+ wsService.initialize(httpServer); // HTTP server required
585
+ // Full Socket.io functionality with real-time communication
586
+ ```
587
+
588
+ ## Performance Considerations
589
+
590
+ ### Memory Usage
591
+
592
+ - **In-memory storage**: Connection and room data stored in Map structures
593
+ - **Message history**: Limited by retention policy (default: unlimited, configure manually)
594
+ - **Redis adapter**: Adds pub/sub overhead but enables horizontal scaling
595
+
596
+ ### Scaling
597
+
598
+ | Aspect | Single Instance | Multi-Instance (Redis) |
599
+ |--------|----------------|------------------------|
600
+ | Max connections | ~10,000 | Unlimited (horizontal) |
601
+ | Message latency | <1ms | ~5-10ms (Redis pub/sub) |
602
+ | Memory per connection | ~1KB | ~1KB + Redis overhead |
603
+ | Cross-instance events | No | Yes |
604
+
605
+ ### Best Practices
606
+
607
+ 1. **Limit message history**: Clean up old messages periodically
608
+ 2. **Use rooms efficiently**: Group users logically, avoid too many small rooms
609
+ 3. **Monitor connections**: Use `getStats()` to track active connections
610
+ 4. **Set reasonable timeouts**: Adjust `pingTimeout` and `pingInterval` for your use case
611
+ 5. **Enable Redis for production**: Always use Redis adapter for multi-instance deployments
612
+ 6. **Clean up inactive connections**: Run `cleanup()` periodically (e.g., every hour)
613
+
614
+ ## Troubleshooting
615
+
616
+ ### Socket.io not working
617
+
618
+ **Problem**: Clients can't connect.
619
+
620
+ **Solution**:
621
+ 1. Ensure HTTP server is passed to `initialize(httpServer)`
622
+ 2. Check CORS configuration matches client origin
623
+ 3. Verify path matches client configuration
624
+ 4. Check firewall allows WebSocket connections
625
+
626
+ ### Messages not reaching all instances
627
+
628
+ **Problem**: In multi-instance setup, messages only reach users on same server.
629
+
630
+ **Solution**:
631
+ 1. Ensure Redis is configured in `WebSocketConfig`
632
+ 2. Verify Redis pub/sub clients are connected (check logs)
633
+ 3. Check Redis host/port/password are correct
634
+ 4. Ensure all instances use same Redis server
635
+
636
+ ### High memory usage
637
+
638
+ **Problem**: Memory grows over time.
639
+
640
+ **Solution**:
641
+ - Run `cleanup()` periodically to remove inactive connections
642
+ - Limit message history retention
643
+ - Monitor room count and clean up unused rooms
644
+
645
+ ### Connection drops
646
+
647
+ **Problem**: Users frequently disconnected.
648
+
649
+ **Solution**:
650
+ - Increase `pingTimeout` (default 60s)
651
+ - Adjust `pingInterval` (default 25s)
652
+ - Check network stability
653
+ - Verify client reconnection logic
654
+
655
+ ## Testing
656
+
657
+ Run WebSocket integration tests:
658
+
659
+ ```bash
660
+ # Ensure HTTP server available
661
+ npm test tests/integration/websocket-socketio.test.ts
662
+ ```
663
+
664
+ **Note**: Tests create HTTP server on port 3010 automatically.
665
+
666
+ ## Related Modules
667
+
668
+ - **Auth Module**: Authenticate WebSocket connections
669
+ - **User Module**: Track user presence and status
670
+ - **Notification Module**: Send real-time notifications
671
+
672
+ ## Changelog
673
+
674
+ ### v0.2.0 (2025-12-19)
675
+
676
+ **WEBSOCKET-001 Completed:**
677
+ - ✅ Connected real Socket.io with HTTP server
678
+ - ✅ Implemented Redis adapter for multi-instance support
679
+ - ✅ Replaced all placeholder broadcasts with real Socket.io emits
680
+ - ✅ Added connection lifecycle handlers (connect, disconnect)
681
+ - ✅ Added event handlers (room:join, room:leave, message, typing)
682
+ - ✅ Implemented graceful shutdown with Redis cleanup
683
+ - ✅ Added 26 comprehensive integration tests
684
+ - ✅ Added this documentation
685
+
686
+ ### v0.1.0 (Initial)
687
+
688
+ - Mock Socket.io implementation
689
+ - In-memory storage only
690
+ - No real WebSocket connections
691
+ - Placeholder broadcasts (logged only)