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,134 @@
1
+ import type { Request, Response, NextFunction, RequestHandler } from 'express';
2
+ import type { RateLimitConfig } from './types.js';
3
+ import { RateLimitService } from './rate-limit.service.js';
4
+
5
+ interface RequestWithUser extends Request {
6
+ user?: {
7
+ id?: string;
8
+ role?: string;
9
+ };
10
+ rateLimiter?: RateLimitService;
11
+ }
12
+
13
+ /**
14
+ * Create rate limiting middleware
15
+ */
16
+ export function createRateLimiter(
17
+ config: RateLimitConfig,
18
+ service?: RateLimitService
19
+ ): RequestHandler {
20
+ const rateLimiter = service || new RateLimitService(config);
21
+
22
+ return async (req: Request, res: Response, next: NextFunction): Promise<void> => {
23
+ try {
24
+ const reqWithUser = req as RequestWithUser;
25
+
26
+ // Generate key for this request
27
+ const key = config.keyGenerator
28
+ ? config.keyGenerator({
29
+ ip: req.ip || 'unknown',
30
+ method: req.method,
31
+ url: req.url,
32
+ path: req.path,
33
+ userId: reqWithUser.user?.id,
34
+ userRole: reqWithUser.user?.role,
35
+ headers: req.headers as Record<string, string | string[] | undefined>,
36
+ })
37
+ : req.ip || 'unknown';
38
+
39
+ // Check for custom limits based on endpoint or user role
40
+ const customMax = config.max;
41
+ const customWindowMs = config.windowMs;
42
+
43
+ // Check rate limit
44
+ const result = await rateLimiter.check(key, {
45
+ max: customMax,
46
+ windowMs: customWindowMs,
47
+ });
48
+
49
+ // Set rate limit headers
50
+ res.setHeader('X-RateLimit-Limit', result.limit.toString());
51
+ res.setHeader('X-RateLimit-Remaining', result.remaining.toString());
52
+ res.setHeader('X-RateLimit-Reset', new Date(result.resetAt).toISOString());
53
+
54
+ if (!result.allowed) {
55
+ if (result.retryAfter) {
56
+ res.setHeader('Retry-After', result.retryAfter.toString());
57
+ }
58
+
59
+ // Default response
60
+ res.status(429).json({
61
+ error: 'Too Many Requests',
62
+ message: 'Rate limit exceeded. Please try again later.',
63
+ limit: result.limit,
64
+ remaining: result.remaining,
65
+ resetAt: new Date(result.resetAt).toISOString(),
66
+ retryAfter: result.retryAfter,
67
+ });
68
+ return;
69
+ }
70
+
71
+ // Store rate limiter service on request for later use
72
+ reqWithUser.rateLimiter = rateLimiter;
73
+
74
+ next();
75
+ } catch (error) {
76
+ console.error('[RateLimitMiddleware] Error:', error);
77
+ // On error, allow the request to proceed
78
+ next();
79
+ }
80
+ };
81
+ }
82
+
83
+ /**
84
+ * Create endpoint-specific rate limiter
85
+ */
86
+ export function rateLimitEndpoint(
87
+ max: number,
88
+ windowMs: number,
89
+ keyGenerator?: (req: Request) => string
90
+ ): RequestHandler {
91
+ const config: RateLimitConfig = {
92
+ max,
93
+ windowMs,
94
+ keyGenerator: keyGenerator
95
+ ? (reqData): string => keyGenerator(reqData as unknown as Request)
96
+ : undefined,
97
+ };
98
+
99
+ return createRateLimiter(config);
100
+ }
101
+
102
+ /**
103
+ * Pre-configured rate limiters for common use cases
104
+ */
105
+
106
+ // Strict - for sensitive operations
107
+ export const strictRateLimit = rateLimitEndpoint(5, 60 * 1000); // 5 requests per minute
108
+
109
+ // Standard - for normal API endpoints
110
+ export const standardRateLimit = rateLimitEndpoint(100, 60 * 1000); // 100 requests per minute
111
+
112
+ // Relaxed - for public endpoints
113
+ export const relaxedRateLimit = rateLimitEndpoint(1000, 60 * 1000); // 1000 requests per minute
114
+
115
+ // Auth endpoints - for login/register
116
+ export const authRateLimit = rateLimitEndpoint(5, 15 * 60 * 1000); // 5 requests per 15 minutes
117
+
118
+ // By IP
119
+ export const ipRateLimit = (max: number, windowMs: number): RequestHandler =>
120
+ rateLimitEndpoint(max, windowMs, (req) => req.ip || 'unknown');
121
+
122
+ // By User ID
123
+ export const userRateLimit = (max: number, windowMs: number): RequestHandler =>
124
+ rateLimitEndpoint(max, windowMs, (req) => {
125
+ const user = (req as RequestWithUser).user;
126
+ return user?.id || req.ip || 'unknown';
127
+ });
128
+
129
+ // By API Key
130
+ export const apiKeyRateLimit = (max: number, windowMs: number): RequestHandler =>
131
+ rateLimitEndpoint(max, windowMs, (req) => {
132
+ const apiKey = req.headers['x-api-key'] as string;
133
+ return apiKey || req.ip || 'unknown';
134
+ });
@@ -0,0 +1,269 @@
1
+ import type { Response } from 'express';
2
+ import { Router, type Request } from 'express';
3
+ import type { RateLimitService } from './rate-limit.service.js';
4
+
5
+ /**
6
+ * Create admin routes for rate limit management
7
+ * These routes should be protected with authentication/authorization middleware
8
+ */
9
+ export function createRateLimitRoutes(service: RateLimitService): Router {
10
+ const router = Router();
11
+
12
+ /**
13
+ * GET /rate-limit/info/:key
14
+ * Get rate limit info for a specific key
15
+ */
16
+ router.get('/info/:key', async (req: Request, res: Response): Promise<void> => {
17
+ try {
18
+ const key = req.params.key;
19
+ if (!key) {
20
+ res.status(400).json({
21
+ error: 'Bad Request',
22
+ message: 'Key is required',
23
+ });
24
+ return;
25
+ }
26
+ const info = await service.getInfo(key);
27
+
28
+ if (!info) {
29
+ res.status(404).json({
30
+ error: 'Not Found',
31
+ message: 'No rate limit data found for this key',
32
+ });
33
+ return;
34
+ }
35
+
36
+ res.json({
37
+ success: true,
38
+ data: info,
39
+ });
40
+ } catch (error) {
41
+ console.error('[RateLimitRoutes] Error getting info:', error);
42
+ res.status(500).json({
43
+ error: 'Internal Server Error',
44
+ message: 'Failed to get rate limit info',
45
+ });
46
+ }
47
+ });
48
+
49
+ /**
50
+ * POST /rate-limit/reset/:key
51
+ * Reset rate limit for a specific key
52
+ */
53
+ router.post('/reset/:key', async (req: Request, res: Response): Promise<void> => {
54
+ try {
55
+ const key = req.params.key;
56
+ if (!key) {
57
+ res.status(400).json({
58
+ error: 'Bad Request',
59
+ message: 'Key is required',
60
+ });
61
+ return;
62
+ }
63
+ await service.reset(key);
64
+
65
+ res.json({
66
+ success: true,
67
+ message: `Rate limit reset for key: ${key}`,
68
+ });
69
+ } catch (error) {
70
+ console.error('[RateLimitRoutes] Error resetting:', error);
71
+ res.status(500).json({
72
+ error: 'Internal Server Error',
73
+ message: 'Failed to reset rate limit',
74
+ });
75
+ }
76
+ });
77
+
78
+ /**
79
+ * GET /rate-limit/config
80
+ * Get current rate limit configuration
81
+ */
82
+ router.get('/config', async (req: Request, res: Response) => {
83
+ try {
84
+ const config = service.getConfig();
85
+
86
+ res.json({
87
+ success: true,
88
+ data: {
89
+ max: config.max,
90
+ windowMs: config.windowMs,
91
+ algorithm: config.algorithm,
92
+ whitelistCount: config.whitelist?.length || 0,
93
+ blacklistCount: config.blacklist?.length || 0,
94
+ customLimitsCount: Object.keys(config.customLimits || {}).length,
95
+ },
96
+ });
97
+ } catch (error) {
98
+ console.error('[RateLimitRoutes] Error getting config:', error);
99
+ res.status(500).json({
100
+ error: 'Internal Server Error',
101
+ message: 'Failed to get configuration',
102
+ });
103
+ }
104
+ });
105
+
106
+ /**
107
+ * POST /rate-limit/whitelist
108
+ * Add IP to whitelist
109
+ */
110
+ router.post('/whitelist', async (req: Request, res: Response): Promise<void> => {
111
+ try {
112
+ const { ip } = req.body as { ip?: string };
113
+
114
+ if (!ip) {
115
+ res.status(400).json({
116
+ error: 'Bad Request',
117
+ message: 'IP address is required',
118
+ });
119
+ return;
120
+ }
121
+
122
+ service.addToWhitelist(ip);
123
+
124
+ res.json({
125
+ success: true,
126
+ message: `IP ${ip} added to whitelist`,
127
+ });
128
+ } catch (error) {
129
+ console.error('[RateLimitRoutes] Error adding to whitelist:', error);
130
+ res.status(500).json({
131
+ error: 'Internal Server Error',
132
+ message: 'Failed to add IP to whitelist',
133
+ });
134
+ }
135
+ });
136
+
137
+ /**
138
+ * DELETE /rate-limit/whitelist/:ip
139
+ * Remove IP from whitelist
140
+ */
141
+ router.delete('/whitelist/:ip', async (req: Request, res: Response): Promise<void> => {
142
+ try {
143
+ const ip = req.params.ip;
144
+ if (!ip) {
145
+ res.status(400).json({
146
+ error: 'Bad Request',
147
+ message: 'IP is required',
148
+ });
149
+ return;
150
+ }
151
+ service.removeFromWhitelist(ip);
152
+
153
+ res.json({
154
+ success: true,
155
+ message: `IP ${ip} removed from whitelist`,
156
+ });
157
+ } catch (error) {
158
+ console.error('[RateLimitRoutes] Error removing from whitelist:', error);
159
+ res.status(500).json({
160
+ error: 'Internal Server Error',
161
+ message: 'Failed to remove IP from whitelist',
162
+ });
163
+ }
164
+ });
165
+
166
+ /**
167
+ * POST /rate-limit/blacklist
168
+ * Add IP to blacklist
169
+ */
170
+ router.post('/blacklist', async (req: Request, res: Response): Promise<void> => {
171
+ try {
172
+ const { ip } = req.body as { ip?: string };
173
+
174
+ if (!ip) {
175
+ res.status(400).json({
176
+ error: 'Bad Request',
177
+ message: 'IP address is required',
178
+ });
179
+ return;
180
+ }
181
+
182
+ service.addToBlacklist(ip);
183
+
184
+ res.json({
185
+ success: true,
186
+ message: `IP ${ip} added to blacklist`,
187
+ });
188
+ } catch (error) {
189
+ console.error('[RateLimitRoutes] Error adding to blacklist:', error);
190
+ res.status(500).json({
191
+ error: 'Internal Server Error',
192
+ message: 'Failed to add IP to blacklist',
193
+ });
194
+ }
195
+ });
196
+
197
+ /**
198
+ * DELETE /rate-limit/blacklist/:ip
199
+ * Remove IP from blacklist
200
+ */
201
+ router.delete('/blacklist/:ip', async (req: Request, res: Response): Promise<void> => {
202
+ try {
203
+ const ip = req.params.ip;
204
+ if (!ip) {
205
+ res.status(400).json({
206
+ error: 'Bad Request',
207
+ message: 'IP is required',
208
+ });
209
+ return;
210
+ }
211
+ service.removeFromBlacklist(ip);
212
+
213
+ res.json({
214
+ success: true,
215
+ message: `IP ${ip} removed from blacklist`,
216
+ });
217
+ } catch (error) {
218
+ console.error('[RateLimitRoutes] Error removing from blacklist:', error);
219
+ res.status(500).json({
220
+ error: 'Internal Server Error',
221
+ message: 'Failed to remove IP from blacklist',
222
+ });
223
+ }
224
+ });
225
+
226
+ /**
227
+ * POST /rate-limit/clear
228
+ * Clear all rate limit data
229
+ */
230
+ router.post('/clear', async (req: Request, res: Response) => {
231
+ try {
232
+ await service.clear();
233
+
234
+ res.json({
235
+ success: true,
236
+ message: 'All rate limit data cleared',
237
+ });
238
+ } catch (error) {
239
+ console.error('[RateLimitRoutes] Error clearing data:', error);
240
+ res.status(500).json({
241
+ error: 'Internal Server Error',
242
+ message: 'Failed to clear rate limit data',
243
+ });
244
+ }
245
+ });
246
+
247
+ /**
248
+ * POST /rate-limit/cleanup
249
+ * Cleanup expired entries
250
+ */
251
+ router.post('/cleanup', async (req: Request, res: Response) => {
252
+ try {
253
+ await service.cleanup();
254
+
255
+ res.json({
256
+ success: true,
257
+ message: 'Expired entries cleaned up',
258
+ });
259
+ } catch (error) {
260
+ console.error('[RateLimitRoutes] Error cleaning up:', error);
261
+ res.status(500).json({
262
+ error: 'Internal Server Error',
263
+ message: 'Failed to cleanup expired entries',
264
+ });
265
+ }
266
+ });
267
+
268
+ return router;
269
+ }