servcraft 0.1.0 → 0.1.1

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 (216) hide show
  1. package/.claude/settings.local.json +29 -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/README.md +1070 -1
  9. package/dist/cli/index.cjs +2026 -2168
  10. package/dist/cli/index.cjs.map +1 -1
  11. package/dist/cli/index.js +2026 -2168
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/index.cjs +595 -616
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.d.cts +114 -52
  16. package/dist/index.d.ts +114 -52
  17. package/dist/index.js +595 -616
  18. package/dist/index.js.map +1 -1
  19. package/docs/CLI-001_MULTI_DB_PLAN.md +546 -0
  20. package/docs/DATABASE_MULTI_ORM.md +399 -0
  21. package/docs/PHASE1_BREAKDOWN.md +346 -0
  22. package/docs/PROGRESS.md +550 -0
  23. package/docs/modules/ANALYTICS.md +226 -0
  24. package/docs/modules/API-VERSIONING.md +252 -0
  25. package/docs/modules/AUDIT.md +192 -0
  26. package/docs/modules/AUTH.md +431 -0
  27. package/docs/modules/CACHE.md +346 -0
  28. package/docs/modules/EMAIL.md +254 -0
  29. package/docs/modules/FEATURE-FLAG.md +291 -0
  30. package/docs/modules/I18N.md +294 -0
  31. package/docs/modules/MEDIA-PROCESSING.md +281 -0
  32. package/docs/modules/MFA.md +266 -0
  33. package/docs/modules/NOTIFICATION.md +311 -0
  34. package/docs/modules/OAUTH.md +237 -0
  35. package/docs/modules/PAYMENT.md +804 -0
  36. package/docs/modules/QUEUE.md +540 -0
  37. package/docs/modules/RATE-LIMIT.md +339 -0
  38. package/docs/modules/SEARCH.md +288 -0
  39. package/docs/modules/SECURITY.md +327 -0
  40. package/docs/modules/SESSION.md +382 -0
  41. package/docs/modules/SWAGGER.md +305 -0
  42. package/docs/modules/UPLOAD.md +296 -0
  43. package/docs/modules/USER.md +505 -0
  44. package/docs/modules/VALIDATION.md +294 -0
  45. package/docs/modules/WEBHOOK.md +270 -0
  46. package/docs/modules/WEBSOCKET.md +691 -0
  47. package/package.json +53 -38
  48. package/prisma/schema.prisma +395 -1
  49. package/src/cli/commands/add-module.ts +520 -87
  50. package/src/cli/commands/db.ts +3 -4
  51. package/src/cli/commands/docs.ts +256 -6
  52. package/src/cli/commands/generate.ts +12 -19
  53. package/src/cli/commands/init.ts +384 -214
  54. package/src/cli/index.ts +0 -4
  55. package/src/cli/templates/repository.ts +6 -1
  56. package/src/cli/templates/routes.ts +6 -21
  57. package/src/cli/utils/docs-generator.ts +6 -7
  58. package/src/cli/utils/env-manager.ts +717 -0
  59. package/src/cli/utils/field-parser.ts +16 -7
  60. package/src/cli/utils/interactive-prompt.ts +223 -0
  61. package/src/cli/utils/template-manager.ts +346 -0
  62. package/src/config/database.config.ts +183 -0
  63. package/src/config/env.ts +0 -10
  64. package/src/config/index.ts +0 -14
  65. package/src/core/server.ts +1 -1
  66. package/src/database/adapters/mongoose.adapter.ts +132 -0
  67. package/src/database/adapters/prisma.adapter.ts +118 -0
  68. package/src/database/connection.ts +190 -0
  69. package/src/database/interfaces/database.interface.ts +85 -0
  70. package/src/database/interfaces/index.ts +7 -0
  71. package/src/database/interfaces/repository.interface.ts +129 -0
  72. package/src/database/models/mongoose/index.ts +7 -0
  73. package/src/database/models/mongoose/payment.schema.ts +347 -0
  74. package/src/database/models/mongoose/user.schema.ts +154 -0
  75. package/src/database/prisma.ts +1 -4
  76. package/src/database/redis.ts +101 -0
  77. package/src/database/repositories/mongoose/index.ts +7 -0
  78. package/src/database/repositories/mongoose/payment.repository.ts +380 -0
  79. package/src/database/repositories/mongoose/user.repository.ts +255 -0
  80. package/src/database/seed.ts +6 -1
  81. package/src/index.ts +9 -20
  82. package/src/middleware/security.ts +2 -6
  83. package/src/modules/analytics/analytics.routes.ts +80 -0
  84. package/src/modules/analytics/analytics.service.ts +364 -0
  85. package/src/modules/analytics/index.ts +18 -0
  86. package/src/modules/analytics/types.ts +180 -0
  87. package/src/modules/api-versioning/index.ts +15 -0
  88. package/src/modules/api-versioning/types.ts +86 -0
  89. package/src/modules/api-versioning/versioning.middleware.ts +120 -0
  90. package/src/modules/api-versioning/versioning.routes.ts +54 -0
  91. package/src/modules/api-versioning/versioning.service.ts +189 -0
  92. package/src/modules/audit/audit.repository.ts +206 -0
  93. package/src/modules/audit/audit.service.ts +27 -59
  94. package/src/modules/auth/auth.controller.ts +2 -2
  95. package/src/modules/auth/auth.middleware.ts +3 -9
  96. package/src/modules/auth/auth.routes.ts +10 -107
  97. package/src/modules/auth/auth.service.ts +126 -23
  98. package/src/modules/auth/index.ts +3 -4
  99. package/src/modules/cache/cache.service.ts +367 -0
  100. package/src/modules/cache/index.ts +10 -0
  101. package/src/modules/cache/types.ts +44 -0
  102. package/src/modules/email/email.service.ts +3 -10
  103. package/src/modules/email/templates.ts +2 -8
  104. package/src/modules/feature-flag/feature-flag.repository.ts +303 -0
  105. package/src/modules/feature-flag/feature-flag.routes.ts +247 -0
  106. package/src/modules/feature-flag/feature-flag.service.ts +566 -0
  107. package/src/modules/feature-flag/index.ts +20 -0
  108. package/src/modules/feature-flag/types.ts +192 -0
  109. package/src/modules/i18n/i18n.middleware.ts +186 -0
  110. package/src/modules/i18n/i18n.routes.ts +191 -0
  111. package/src/modules/i18n/i18n.service.ts +456 -0
  112. package/src/modules/i18n/index.ts +18 -0
  113. package/src/modules/i18n/types.ts +118 -0
  114. package/src/modules/media-processing/index.ts +17 -0
  115. package/src/modules/media-processing/media-processing.routes.ts +111 -0
  116. package/src/modules/media-processing/media-processing.service.ts +245 -0
  117. package/src/modules/media-processing/types.ts +156 -0
  118. package/src/modules/mfa/index.ts +20 -0
  119. package/src/modules/mfa/mfa.repository.ts +206 -0
  120. package/src/modules/mfa/mfa.routes.ts +595 -0
  121. package/src/modules/mfa/mfa.service.ts +572 -0
  122. package/src/modules/mfa/totp.ts +150 -0
  123. package/src/modules/mfa/types.ts +57 -0
  124. package/src/modules/notification/index.ts +20 -0
  125. package/src/modules/notification/notification.repository.ts +356 -0
  126. package/src/modules/notification/notification.service.ts +483 -0
  127. package/src/modules/notification/types.ts +119 -0
  128. package/src/modules/oauth/index.ts +20 -0
  129. package/src/modules/oauth/oauth.repository.ts +219 -0
  130. package/src/modules/oauth/oauth.routes.ts +446 -0
  131. package/src/modules/oauth/oauth.service.ts +293 -0
  132. package/src/modules/oauth/providers/apple.provider.ts +250 -0
  133. package/src/modules/oauth/providers/facebook.provider.ts +181 -0
  134. package/src/modules/oauth/providers/github.provider.ts +248 -0
  135. package/src/modules/oauth/providers/google.provider.ts +189 -0
  136. package/src/modules/oauth/providers/twitter.provider.ts +214 -0
  137. package/src/modules/oauth/types.ts +94 -0
  138. package/src/modules/payment/index.ts +19 -0
  139. package/src/modules/payment/payment.repository.ts +733 -0
  140. package/src/modules/payment/payment.routes.ts +390 -0
  141. package/src/modules/payment/payment.service.ts +354 -0
  142. package/src/modules/payment/providers/mobile-money.provider.ts +274 -0
  143. package/src/modules/payment/providers/paypal.provider.ts +190 -0
  144. package/src/modules/payment/providers/stripe.provider.ts +215 -0
  145. package/src/modules/payment/types.ts +140 -0
  146. package/src/modules/queue/cron.ts +438 -0
  147. package/src/modules/queue/index.ts +87 -0
  148. package/src/modules/queue/queue.routes.ts +600 -0
  149. package/src/modules/queue/queue.service.ts +842 -0
  150. package/src/modules/queue/types.ts +222 -0
  151. package/src/modules/queue/workers.ts +366 -0
  152. package/src/modules/rate-limit/index.ts +59 -0
  153. package/src/modules/rate-limit/rate-limit.middleware.ts +134 -0
  154. package/src/modules/rate-limit/rate-limit.routes.ts +269 -0
  155. package/src/modules/rate-limit/rate-limit.service.ts +348 -0
  156. package/src/modules/rate-limit/stores/memory.store.ts +165 -0
  157. package/src/modules/rate-limit/stores/redis.store.ts +322 -0
  158. package/src/modules/rate-limit/types.ts +153 -0
  159. package/src/modules/search/adapters/elasticsearch.adapter.ts +326 -0
  160. package/src/modules/search/adapters/meilisearch.adapter.ts +261 -0
  161. package/src/modules/search/adapters/memory.adapter.ts +278 -0
  162. package/src/modules/search/index.ts +21 -0
  163. package/src/modules/search/search.service.ts +234 -0
  164. package/src/modules/search/types.ts +214 -0
  165. package/src/modules/security/index.ts +40 -0
  166. package/src/modules/security/sanitize.ts +223 -0
  167. package/src/modules/security/security-audit.service.ts +388 -0
  168. package/src/modules/security/security.middleware.ts +398 -0
  169. package/src/modules/session/index.ts +3 -0
  170. package/src/modules/session/session.repository.ts +159 -0
  171. package/src/modules/session/session.service.ts +340 -0
  172. package/src/modules/session/types.ts +38 -0
  173. package/src/modules/swagger/index.ts +7 -1
  174. package/src/modules/swagger/schema-builder.ts +16 -4
  175. package/src/modules/swagger/swagger.service.ts +9 -10
  176. package/src/modules/swagger/types.ts +0 -2
  177. package/src/modules/upload/index.ts +14 -0
  178. package/src/modules/upload/types.ts +83 -0
  179. package/src/modules/upload/upload.repository.ts +199 -0
  180. package/src/modules/upload/upload.routes.ts +311 -0
  181. package/src/modules/upload/upload.service.ts +448 -0
  182. package/src/modules/user/index.ts +3 -3
  183. package/src/modules/user/user.controller.ts +15 -9
  184. package/src/modules/user/user.repository.ts +237 -113
  185. package/src/modules/user/user.routes.ts +39 -164
  186. package/src/modules/user/user.service.ts +4 -3
  187. package/src/modules/validation/validator.ts +12 -17
  188. package/src/modules/webhook/index.ts +91 -0
  189. package/src/modules/webhook/retry.ts +196 -0
  190. package/src/modules/webhook/signature.ts +135 -0
  191. package/src/modules/webhook/types.ts +181 -0
  192. package/src/modules/webhook/webhook.repository.ts +358 -0
  193. package/src/modules/webhook/webhook.routes.ts +442 -0
  194. package/src/modules/webhook/webhook.service.ts +457 -0
  195. package/src/modules/websocket/features.ts +504 -0
  196. package/src/modules/websocket/index.ts +106 -0
  197. package/src/modules/websocket/middlewares.ts +298 -0
  198. package/src/modules/websocket/types.ts +181 -0
  199. package/src/modules/websocket/websocket.service.ts +692 -0
  200. package/src/utils/errors.ts +7 -0
  201. package/src/utils/pagination.ts +4 -1
  202. package/tests/helpers/db-check.ts +79 -0
  203. package/tests/integration/auth-redis.test.ts +94 -0
  204. package/tests/integration/cache-redis.test.ts +387 -0
  205. package/tests/integration/mongoose-repositories.test.ts +410 -0
  206. package/tests/integration/payment-prisma.test.ts +637 -0
  207. package/tests/integration/queue-bullmq.test.ts +417 -0
  208. package/tests/integration/user-prisma.test.ts +441 -0
  209. package/tests/integration/websocket-socketio.test.ts +552 -0
  210. package/tests/setup.ts +11 -9
  211. package/vitest.config.ts +3 -8
  212. package/npm-cache/_cacache/content-v2/sha512/1c/d0/03440d500a0487621aad1d6402978340698976602046db8e24fa03c01ee6c022c69b0582f969042d9442ee876ac35c038e960dd427d1e622fa24b8eb7dba +0 -0
  213. package/npm-cache/_cacache/content-v2/sha512/42/55/28b493ca491833e5aab0e9c3108d29ab3f36c248ca88f45d4630674fce9130959e56ae308797ac2b6328fa7f09a610b9550ed09cb971d039876d293fc69d +0 -0
  214. package/npm-cache/_cacache/content-v2/sha512/e0/12/f360dc9315ee5f17844a0c8c233ee6bf7c30837c4a02ea0d56c61c7f7ab21c0e958e50ed2c57c59f983c762b93056778c9009b2398ffc26def0183999b13 +0 -0
  215. package/npm-cache/_cacache/content-v2/sha512/ed/b0/fae1161902898f4c913c67d7f6cdf6be0665aec3b389b9c4f4f0a101ca1da59badf1b59c4e0030f5223023b8d63cfe501c46a32c20c895d4fb3f11ca2232 +0 -0
  216. package/npm-cache/_cacache/index-v5/58/94/c2cba79e0f16b4c10e95a87e32255741149e8222cc314a476aab67c39cc0 +0 -5
@@ -0,0 +1,298 @@
1
+ import { logger } from '../../core/logger.js';
2
+ import type { SocketMiddleware, AuthenticatedSocket } from './types.js';
3
+
4
+ /**
5
+ * Authentication Middleware
6
+ * Validates JWT token from socket handshake
7
+ */
8
+ export function authMiddleware(): SocketMiddleware {
9
+ return (socket: unknown, next: (err?: Error) => void) => {
10
+ const authSocket = socket as AuthenticatedSocket;
11
+
12
+ try {
13
+ // Get token from auth or query
14
+ const token = authSocket.handshake.auth?.token || authSocket.handshake.query?.token;
15
+
16
+ if (!token) {
17
+ return next(new Error('Authentication token missing'));
18
+ }
19
+
20
+ // Verify token (mock - in production use JWT library)
21
+ // const decoded = jwt.verify(token, process.env.JWT_SECRET);
22
+ // authSocket.userId = decoded.userId;
23
+ // authSocket.user = decoded;
24
+
25
+ // Mock authentication
26
+ authSocket.userId = 'user_123';
27
+
28
+ logger.debug({ socketId: authSocket.id, userId: authSocket.userId }, 'Socket authenticated');
29
+
30
+ next();
31
+ } catch (error) {
32
+ logger.error({ error, socketId: authSocket.id }, 'Socket authentication failed');
33
+ next(new Error('Authentication failed'));
34
+ }
35
+ };
36
+ }
37
+
38
+ /**
39
+ * Rate Limiting Middleware
40
+ * Limits socket connections per IP
41
+ */
42
+ export function rateLimitMiddleware(maxConnections = 5, windowMs = 60000): SocketMiddleware {
43
+ const connections = new Map<string, { count: number; resetAt: number }>();
44
+
45
+ return (socket: unknown, next: (err?: Error) => void) => {
46
+ const authSocket = socket as AuthenticatedSocket;
47
+ const ip =
48
+ authSocket.handshake.headers['x-forwarded-for'] ||
49
+ authSocket.handshake.headers['x-real-ip'] ||
50
+ 'unknown';
51
+
52
+ const now = Date.now();
53
+ const key = ip as string;
54
+
55
+ // Clean up expired entries
56
+ for (const [k, v] of connections.entries()) {
57
+ if (v.resetAt < now) {
58
+ connections.delete(k);
59
+ }
60
+ }
61
+
62
+ // Check rate limit
63
+ const entry = connections.get(key);
64
+
65
+ if (entry && entry.count >= maxConnections) {
66
+ logger.warn({ ip, count: entry.count }, 'Socket rate limit exceeded');
67
+ return next(new Error('Too many connections'));
68
+ }
69
+
70
+ // Update count
71
+ if (entry) {
72
+ entry.count++;
73
+ } else {
74
+ connections.set(key, {
75
+ count: 1,
76
+ resetAt: now + windowMs,
77
+ });
78
+ }
79
+
80
+ // Cleanup on disconnect
81
+ authSocket.on('disconnect', () => {
82
+ const entry = connections.get(key);
83
+ if (entry) {
84
+ entry.count = Math.max(0, entry.count - 1);
85
+ }
86
+ });
87
+
88
+ next();
89
+ };
90
+ }
91
+
92
+ /**
93
+ * CORS Middleware
94
+ * Validates origin
95
+ */
96
+ export function corsMiddleware(allowedOrigins: string[]): SocketMiddleware {
97
+ return (socket: unknown, next: (err?: Error) => void) => {
98
+ const authSocket = socket as AuthenticatedSocket;
99
+ const origin = authSocket.handshake.headers.origin;
100
+
101
+ if (!origin) {
102
+ return next(new Error('Origin not specified'));
103
+ }
104
+
105
+ if (allowedOrigins.includes('*') || allowedOrigins.includes(origin)) {
106
+ next();
107
+ } else {
108
+ logger.warn({ origin, socketId: authSocket.id }, 'Origin not allowed');
109
+ next(new Error('Origin not allowed'));
110
+ }
111
+ };
112
+ }
113
+
114
+ /**
115
+ * Logging Middleware
116
+ * Logs all socket events
117
+ */
118
+ export function loggingMiddleware(): SocketMiddleware {
119
+ return (socket: unknown, next: (err?: Error) => void) => {
120
+ const authSocket = socket as AuthenticatedSocket;
121
+
122
+ logger.info(
123
+ {
124
+ socketId: authSocket.id,
125
+ userId: authSocket.userId,
126
+ ip: authSocket.handshake.headers['x-forwarded-for'] || 'unknown',
127
+ userAgent: authSocket.handshake.headers['user-agent'],
128
+ },
129
+ 'Socket connecting'
130
+ );
131
+
132
+ // Log all events
133
+ const originalEmit = authSocket.emit;
134
+ authSocket.emit = function (event: string, ...args: unknown[]): boolean {
135
+ logger.debug({ socketId: authSocket.id, event, argsCount: args.length }, 'Socket emit');
136
+ return originalEmit.call(this, event, ...args);
137
+ };
138
+
139
+ next();
140
+ };
141
+ }
142
+
143
+ /**
144
+ * Validation Middleware
145
+ * Validates socket handshake data
146
+ */
147
+ export function validationMiddleware(requiredFields: string[]): SocketMiddleware {
148
+ return (socket: unknown, next: (err?: Error) => void) => {
149
+ const authSocket = socket as AuthenticatedSocket;
150
+ const data = { ...authSocket.handshake.auth, ...authSocket.handshake.query };
151
+
152
+ for (const field of requiredFields) {
153
+ if (!data[field]) {
154
+ logger.warn({ socketId: authSocket.id, field }, 'Required field missing');
155
+ return next(new Error(`Required field missing: ${field}`));
156
+ }
157
+ }
158
+
159
+ next();
160
+ };
161
+ }
162
+
163
+ /**
164
+ * Role-based Access Middleware
165
+ * Restricts access based on user roles
166
+ */
167
+ export function roleMiddleware(allowedRoles: string[]): SocketMiddleware {
168
+ return (socket: unknown, next: (err?: Error) => void) => {
169
+ const authSocket = socket as AuthenticatedSocket;
170
+
171
+ if (!authSocket.user) {
172
+ return next(new Error('User not authenticated'));
173
+ }
174
+
175
+ const userRoles = authSocket.user.roles || [];
176
+ const hasRole = userRoles.some((role) => allowedRoles.includes(role));
177
+
178
+ if (!hasRole) {
179
+ logger.warn(
180
+ {
181
+ socketId: authSocket.id,
182
+ userId: authSocket.userId,
183
+ requiredRoles: allowedRoles,
184
+ userRoles,
185
+ },
186
+ 'Insufficient permissions'
187
+ );
188
+ return next(new Error('Insufficient permissions'));
189
+ }
190
+
191
+ next();
192
+ };
193
+ }
194
+
195
+ /**
196
+ * Namespace Middleware
197
+ * Validates namespace access
198
+ */
199
+ export function namespaceMiddleware(
200
+ validateAccess: (userId: string, namespace: string) => Promise<boolean>
201
+ ): SocketMiddleware {
202
+ return async (socket: unknown, next: (err?: Error) => void) => {
203
+ const authSocket = socket as AuthenticatedSocket;
204
+ const namespace = authSocket.handshake.query.namespace as string;
205
+
206
+ if (!namespace) {
207
+ return next(new Error('Namespace not specified'));
208
+ }
209
+
210
+ if (!authSocket.userId) {
211
+ return next(new Error('User not authenticated'));
212
+ }
213
+
214
+ try {
215
+ const hasAccess = await validateAccess(authSocket.userId, namespace);
216
+
217
+ if (!hasAccess) {
218
+ logger.warn(
219
+ { socketId: authSocket.id, userId: authSocket.userId, namespace },
220
+ 'Namespace access denied'
221
+ );
222
+ return next(new Error('Access to namespace denied'));
223
+ }
224
+
225
+ next();
226
+ } catch (error) {
227
+ logger.error(
228
+ { error, socketId: authSocket.id, namespace },
229
+ 'Error validating namespace access'
230
+ );
231
+ next(new Error('Failed to validate namespace access'));
232
+ }
233
+ };
234
+ }
235
+
236
+ /**
237
+ * Throttling Middleware
238
+ * Limits event emission rate
239
+ */
240
+ export function throttleMiddleware(maxEvents = 100, windowMs = 1000): SocketMiddleware {
241
+ const eventCounts = new Map<string, { count: number; resetAt: number }>();
242
+
243
+ return (socket: unknown, next: (err?: Error) => void) => {
244
+ const authSocket = socket as AuthenticatedSocket;
245
+
246
+ // Wrap emit to count events
247
+ const originalEmit = authSocket.emit;
248
+ authSocket.emit = function (event: string, ...args: unknown[]): boolean {
249
+ const now = Date.now();
250
+ const key = authSocket.id;
251
+
252
+ const entry = eventCounts.get(key);
253
+
254
+ if (entry && entry.resetAt > now) {
255
+ if (entry.count >= maxEvents) {
256
+ logger.warn(
257
+ { socketId: authSocket.id, event, count: entry.count },
258
+ 'Event throttle limit exceeded'
259
+ );
260
+ return false;
261
+ }
262
+ entry.count++;
263
+ } else {
264
+ eventCounts.set(key, {
265
+ count: 1,
266
+ resetAt: now + windowMs,
267
+ });
268
+ }
269
+
270
+ return originalEmit.call(this, event, ...args);
271
+ };
272
+
273
+ // Cleanup on disconnect
274
+ authSocket.on('disconnect', () => {
275
+ eventCounts.delete(authSocket.id);
276
+ });
277
+
278
+ next();
279
+ };
280
+ }
281
+
282
+ /**
283
+ * Error Handling Middleware
284
+ * Catches and logs errors
285
+ */
286
+ export function errorMiddleware(): SocketMiddleware {
287
+ return (socket: unknown, next: (err?: Error) => void) => {
288
+ const authSocket = socket as AuthenticatedSocket;
289
+
290
+ // Catch all errors
291
+ authSocket.on('error', (...args: unknown[]) => {
292
+ const error = args[0] instanceof Error ? args[0] : new Error(String(args[0]));
293
+ logger.error({ error, socketId: authSocket.id, userId: authSocket.userId }, 'Socket error');
294
+ });
295
+
296
+ next();
297
+ };
298
+ }
@@ -0,0 +1,181 @@
1
+ export interface WebSocketConfig {
2
+ /** CORS origin */
3
+ cors?: {
4
+ origin: string | string[];
5
+ credentials?: boolean;
6
+ };
7
+ /** Path for socket.io */
8
+ path?: string;
9
+ /** Redis adapter for scaling */
10
+ redis?: {
11
+ host: string;
12
+ port: number;
13
+ password?: string;
14
+ };
15
+ /** Enable ping timeout */
16
+ pingTimeout?: number;
17
+ /** Ping interval */
18
+ pingInterval?: number;
19
+ /** Max payload size */
20
+ maxHttpBufferSize?: number;
21
+ }
22
+
23
+ export interface SocketUser {
24
+ id: string;
25
+ socketId: string;
26
+ username?: string;
27
+ email?: string;
28
+ roles?: string[];
29
+ metadata?: Record<string, unknown>;
30
+ connectedAt: Date;
31
+ lastActivity: Date;
32
+ }
33
+
34
+ export interface Room {
35
+ id: string;
36
+ name: string;
37
+ namespace: string;
38
+ members: Set<string>;
39
+ metadata?: Record<string, unknown>;
40
+ createdAt: Date;
41
+ createdBy?: string;
42
+ }
43
+
44
+ export interface Message {
45
+ id: string;
46
+ roomId: string;
47
+ userId: string;
48
+ username?: string;
49
+ content: string;
50
+ type: 'text' | 'image' | 'file' | 'system';
51
+ metadata?: Record<string, unknown>;
52
+ timestamp: Date;
53
+ edited?: boolean;
54
+ editedAt?: Date;
55
+ }
56
+
57
+ export interface PresenceStatus {
58
+ userId: string;
59
+ status: 'online' | 'away' | 'busy' | 'offline';
60
+ lastSeen: Date;
61
+ metadata?: Record<string, unknown>;
62
+ }
63
+
64
+ export interface Notification {
65
+ id: string;
66
+ userId: string;
67
+ type: string;
68
+ title: string;
69
+ message: string;
70
+ data?: Record<string, unknown>;
71
+ read: boolean;
72
+ createdAt: Date;
73
+ }
74
+
75
+ export interface TypingIndicator {
76
+ userId: string;
77
+ username?: string;
78
+ roomId: string;
79
+ timestamp: Date;
80
+ }
81
+
82
+ export interface WebSocketEvent {
83
+ event: string;
84
+ data: unknown;
85
+ timestamp: Date;
86
+ userId?: string;
87
+ socketId?: string;
88
+ roomId?: string;
89
+ }
90
+
91
+ export interface BroadcastOptions {
92
+ /** Target room */
93
+ room?: string;
94
+ /** Target namespace */
95
+ namespace?: string;
96
+ /** Exclude specific socket IDs */
97
+ except?: string[];
98
+ /** Only send to specific user IDs */
99
+ users?: string[];
100
+ /** Include metadata */
101
+ metadata?: Record<string, unknown>;
102
+ }
103
+
104
+ export interface ConnectionStats {
105
+ totalConnections: number;
106
+ activeConnections: number;
107
+ totalRooms: number;
108
+ messagesPerMinute: number;
109
+ bytesPerMinute: number;
110
+ avgLatency: number;
111
+ }
112
+
113
+ export interface RoomStats {
114
+ roomId: string;
115
+ memberCount: number;
116
+ messageCount: number;
117
+ createdAt: Date;
118
+ lastActivity: Date;
119
+ }
120
+
121
+ // Event types
122
+ export type SocketEventType =
123
+ | 'connection'
124
+ | 'disconnect'
125
+ | 'message'
126
+ | 'typing'
127
+ | 'presence'
128
+ | 'notification'
129
+ | 'room:join'
130
+ | 'room:leave'
131
+ | 'room:create'
132
+ | 'error';
133
+
134
+ // Socket.io event handlers
135
+ export interface SocketHandlers {
136
+ onConnection?: (socket: SocketUser) => void | Promise<void>;
137
+ onDisconnect?: (socket: SocketUser, reason: string) => void | Promise<void>;
138
+ onMessage?: (message: Message) => void | Promise<void>;
139
+ onError?: (error: Error, socket?: SocketUser) => void | Promise<void>;
140
+ }
141
+
142
+ // Middleware types
143
+ export interface SocketMiddleware {
144
+ (socket: unknown, next: (err?: Error) => void): void | Promise<void>;
145
+ }
146
+
147
+ export interface AuthenticatedSocket {
148
+ id: string;
149
+ userId?: string;
150
+ user?: SocketUser;
151
+ rooms: Set<string>;
152
+ handshake: {
153
+ auth: Record<string, unknown>;
154
+ headers: Record<string, string>;
155
+ query: Record<string, string>;
156
+ };
157
+ emit: (event: string, ...args: unknown[]) => boolean;
158
+ on: (event: string, listener: (...args: unknown[]) => void) => void;
159
+ join: (room: string) => void;
160
+ leave: (room: string) => void;
161
+ disconnect: (close?: boolean) => void;
162
+ }
163
+
164
+ export interface ChatMessage extends Message {
165
+ replyTo?: string;
166
+ mentions?: string[];
167
+ attachments?: Array<{
168
+ type: string;
169
+ url: string;
170
+ name: string;
171
+ size: number;
172
+ }>;
173
+ }
174
+
175
+ export interface LiveEvent {
176
+ id: string;
177
+ type: string;
178
+ data: Record<string, unknown>;
179
+ timestamp: Date;
180
+ source?: string;
181
+ }