mcp-server-rocketchat-threads 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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +332 -0
  3. package/dist/api/client.d.ts +119 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/client.js +305 -0
  6. package/dist/api/client.js.map +1 -0
  7. package/dist/api/index.d.ts +6 -0
  8. package/dist/api/index.d.ts.map +1 -0
  9. package/dist/api/index.js +22 -0
  10. package/dist/api/index.js.map +1 -0
  11. package/dist/api/schemas.d.ts +10636 -0
  12. package/dist/api/schemas.d.ts.map +1 -0
  13. package/dist/api/schemas.js +267 -0
  14. package/dist/api/schemas.js.map +1 -0
  15. package/dist/api/types.d.ts +263 -0
  16. package/dist/api/types.d.ts.map +1 -0
  17. package/dist/api/types.js +7 -0
  18. package/dist/api/types.js.map +1 -0
  19. package/dist/config/config.d.ts +37 -0
  20. package/dist/config/config.d.ts.map +1 -0
  21. package/dist/config/config.js +79 -0
  22. package/dist/config/config.js.map +1 -0
  23. package/dist/config/index.d.ts +5 -0
  24. package/dist/config/index.d.ts.map +1 -0
  25. package/dist/config/index.js +21 -0
  26. package/dist/config/index.js.map +1 -0
  27. package/dist/di/container.d.ts +101 -0
  28. package/dist/di/container.d.ts.map +1 -0
  29. package/dist/di/container.js +214 -0
  30. package/dist/di/container.js.map +1 -0
  31. package/dist/di/index.d.ts +6 -0
  32. package/dist/di/index.d.ts.map +1 -0
  33. package/dist/di/index.js +12 -0
  34. package/dist/di/index.js.map +1 -0
  35. package/dist/formatters/index.d.ts +6 -0
  36. package/dist/formatters/index.d.ts.map +1 -0
  37. package/dist/formatters/index.js +22 -0
  38. package/dist/formatters/index.js.map +1 -0
  39. package/dist/formatters/message-formatter.d.ts +64 -0
  40. package/dist/formatters/message-formatter.d.ts.map +1 -0
  41. package/dist/formatters/message-formatter.js +161 -0
  42. package/dist/formatters/message-formatter.js.map +1 -0
  43. package/dist/formatters/response-builder.d.ts +60 -0
  44. package/dist/formatters/response-builder.d.ts.map +1 -0
  45. package/dist/formatters/response-builder.js +108 -0
  46. package/dist/formatters/response-builder.js.map +1 -0
  47. package/dist/guards/index.d.ts +12 -0
  48. package/dist/guards/index.d.ts.map +1 -0
  49. package/dist/guards/index.js +42 -0
  50. package/dist/guards/index.js.map +1 -0
  51. package/dist/guards/input-validator.d.ts +89 -0
  52. package/dist/guards/input-validator.d.ts.map +1 -0
  53. package/dist/guards/input-validator.js +266 -0
  54. package/dist/guards/input-validator.js.map +1 -0
  55. package/dist/guards/rate-limiter.d.ts +115 -0
  56. package/dist/guards/rate-limiter.d.ts.map +1 -0
  57. package/dist/guards/rate-limiter.js +226 -0
  58. package/dist/guards/rate-limiter.js.map +1 -0
  59. package/dist/guards/sanitizer.d.ts +35 -0
  60. package/dist/guards/sanitizer.d.ts.map +1 -0
  61. package/dist/guards/sanitizer.js +111 -0
  62. package/dist/guards/sanitizer.js.map +1 -0
  63. package/dist/guards/write-guard.d.ts +33 -0
  64. package/dist/guards/write-guard.d.ts.map +1 -0
  65. package/dist/guards/write-guard.js +90 -0
  66. package/dist/guards/write-guard.js.map +1 -0
  67. package/dist/http-server.d.ts +9 -0
  68. package/dist/http-server.d.ts.map +1 -0
  69. package/dist/http-server.js +190 -0
  70. package/dist/http-server.js.map +1 -0
  71. package/dist/index.d.ts +14 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +114 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/tools/base.d.ts +85 -0
  76. package/dist/tools/base.d.ts.map +1 -0
  77. package/dist/tools/base.js +184 -0
  78. package/dist/tools/base.js.map +1 -0
  79. package/dist/tools/channel-tools.d.ts +18 -0
  80. package/dist/tools/channel-tools.d.ts.map +1 -0
  81. package/dist/tools/channel-tools.js +151 -0
  82. package/dist/tools/channel-tools.js.map +1 -0
  83. package/dist/tools/handler-utils.d.ts +75 -0
  84. package/dist/tools/handler-utils.d.ts.map +1 -0
  85. package/dist/tools/handler-utils.js +105 -0
  86. package/dist/tools/handler-utils.js.map +1 -0
  87. package/dist/tools/index.d.ts +17 -0
  88. package/dist/tools/index.d.ts.map +1 -0
  89. package/dist/tools/index.js +40 -0
  90. package/dist/tools/index.js.map +1 -0
  91. package/dist/tools/message-tools.d.ts +20 -0
  92. package/dist/tools/message-tools.d.ts.map +1 -0
  93. package/dist/tools/message-tools.js +194 -0
  94. package/dist/tools/message-tools.js.map +1 -0
  95. package/dist/tools/thread-tools.d.ts +23 -0
  96. package/dist/tools/thread-tools.d.ts.map +1 -0
  97. package/dist/tools/thread-tools.js +243 -0
  98. package/dist/tools/thread-tools.js.map +1 -0
  99. package/dist/tools/user-tools.d.ts +14 -0
  100. package/dist/tools/user-tools.d.ts.map +1 -0
  101. package/dist/tools/user-tools.js +120 -0
  102. package/dist/tools/user-tools.js.map +1 -0
  103. package/dist/tools/write-tools.d.ts +15 -0
  104. package/dist/tools/write-tools.d.ts.map +1 -0
  105. package/dist/tools/write-tools.js +181 -0
  106. package/dist/tools/write-tools.js.map +1 -0
  107. package/dist/utils/cache.d.ts +47 -0
  108. package/dist/utils/cache.d.ts.map +1 -0
  109. package/dist/utils/cache.js +116 -0
  110. package/dist/utils/cache.js.map +1 -0
  111. package/dist/utils/error-handler.d.ts +64 -0
  112. package/dist/utils/error-handler.d.ts.map +1 -0
  113. package/dist/utils/error-handler.js +148 -0
  114. package/dist/utils/error-handler.js.map +1 -0
  115. package/dist/utils/index.d.ts +12 -0
  116. package/dist/utils/index.d.ts.map +1 -0
  117. package/dist/utils/index.js +33 -0
  118. package/dist/utils/index.js.map +1 -0
  119. package/dist/utils/logger.d.ts +50 -0
  120. package/dist/utils/logger.d.ts.map +1 -0
  121. package/dist/utils/logger.js +118 -0
  122. package/dist/utils/logger.js.map +1 -0
  123. package/dist/utils/time-parser.d.ts +37 -0
  124. package/dist/utils/time-parser.d.ts.map +1 -0
  125. package/dist/utils/time-parser.js +98 -0
  126. package/dist/utils/time-parser.js.map +1 -0
  127. package/dist/utils/token-counter.d.ts +42 -0
  128. package/dist/utils/token-counter.d.ts.map +1 -0
  129. package/dist/utils/token-counter.js +81 -0
  130. package/dist/utils/token-counter.js.map +1 -0
  131. package/package.json +68 -0
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ /**
3
+ * Input Validator - Validates and sanitizes input parameters
4
+ * Provides defense against injection attacks and malformed input
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.escapeHtml = exports.validateOffset = exports.validateLimit = exports.validateEmoji = exports.validateMessageText = exports.validateQuery = exports.validateUsername = exports.validateUserId = exports.validateMessageId = exports.validateRoomId = exports.InputValidator = exports.MAX_LENGTHS = void 0;
8
+ const logger_js_1 = require("../utils/logger.js");
9
+ const logger = (0, logger_js_1.getLogger)('InputValidator');
10
+ /**
11
+ * Maximum lengths for various input types
12
+ */
13
+ exports.MAX_LENGTHS = {
14
+ roomId: 64,
15
+ messageId: 64,
16
+ threadId: 64,
17
+ userId: 64,
18
+ username: 128,
19
+ query: 500,
20
+ messageText: 10000,
21
+ emoji: 64,
22
+ };
23
+ /**
24
+ * Patterns for valid input formats
25
+ */
26
+ const VALID_PATTERNS = {
27
+ // RocketChat IDs are alphanumeric with some special chars
28
+ id: /^[a-zA-Z0-9_-]+$/,
29
+ // Usernames can contain letters, numbers, dots, hyphens, underscores
30
+ username: /^[a-zA-Z0-9._-]+$/,
31
+ // Emoji names are alphanumeric with underscores, wrapped in colons
32
+ emoji: /^:?[a-zA-Z0-9_+-]+:?$/,
33
+ };
34
+ /**
35
+ * Dangerous patterns to detect in input
36
+ */
37
+ const DANGEROUS_PATTERNS = [
38
+ // MongoDB injection patterns
39
+ /\$where/i,
40
+ /\$gt/i,
41
+ /\$lt/i,
42
+ /\$ne/i,
43
+ /\$regex/i,
44
+ /\$or/i,
45
+ /\$and/i,
46
+ // NoSQL injection
47
+ /\{\s*['"]\$[a-z]+['"]/i,
48
+ // Script injection
49
+ /<script\b/i,
50
+ /javascript:/i,
51
+ /on\w+\s*=/i,
52
+ // Command injection
53
+ /[;&|`$]/,
54
+ ];
55
+ /**
56
+ * Input validator class
57
+ */
58
+ class InputValidator {
59
+ /**
60
+ * Validate a room ID
61
+ */
62
+ static validateRoomId(roomId) {
63
+ if (typeof roomId !== 'string') {
64
+ return { valid: false, error: 'Room ID must be a string' };
65
+ }
66
+ if (!roomId.trim()) {
67
+ return { valid: false, error: 'Room ID cannot be empty' };
68
+ }
69
+ if (roomId.length > exports.MAX_LENGTHS.roomId) {
70
+ return { valid: false, error: `Room ID exceeds maximum length of ${exports.MAX_LENGTHS.roomId}` };
71
+ }
72
+ // Check for dangerous patterns
73
+ if (this.containsDangerousPattern(roomId)) {
74
+ logger.warn('Dangerous pattern detected in room ID', { roomId: roomId.substring(0, 20) });
75
+ return { valid: false, error: 'Room ID contains invalid characters' };
76
+ }
77
+ return { valid: true, sanitized: roomId.trim() };
78
+ }
79
+ /**
80
+ * Validate a message ID
81
+ */
82
+ static validateMessageId(messageId) {
83
+ if (typeof messageId !== 'string') {
84
+ return { valid: false, error: 'Message ID must be a string' };
85
+ }
86
+ if (!messageId.trim()) {
87
+ return { valid: false, error: 'Message ID cannot be empty' };
88
+ }
89
+ if (messageId.length > exports.MAX_LENGTHS.messageId) {
90
+ return { valid: false, error: `Message ID exceeds maximum length of ${exports.MAX_LENGTHS.messageId}` };
91
+ }
92
+ if (!VALID_PATTERNS.id.test(messageId)) {
93
+ return { valid: false, error: 'Message ID contains invalid characters' };
94
+ }
95
+ return { valid: true, sanitized: messageId.trim() };
96
+ }
97
+ /**
98
+ * Validate a user ID
99
+ */
100
+ static validateUserId(userId) {
101
+ if (typeof userId !== 'string') {
102
+ return { valid: false, error: 'User ID must be a string' };
103
+ }
104
+ if (!userId.trim()) {
105
+ return { valid: false, error: 'User ID cannot be empty' };
106
+ }
107
+ if (userId.length > exports.MAX_LENGTHS.userId) {
108
+ return { valid: false, error: `User ID exceeds maximum length of ${exports.MAX_LENGTHS.userId}` };
109
+ }
110
+ if (!VALID_PATTERNS.id.test(userId)) {
111
+ return { valid: false, error: 'User ID contains invalid characters' };
112
+ }
113
+ return { valid: true, sanitized: userId.trim() };
114
+ }
115
+ /**
116
+ * Validate a username
117
+ */
118
+ static validateUsername(username) {
119
+ if (typeof username !== 'string') {
120
+ return { valid: false, error: 'Username must be a string' };
121
+ }
122
+ // Remove @ prefix if present
123
+ const cleaned = username.replace(/^@/, '').trim();
124
+ if (!cleaned) {
125
+ return { valid: false, error: 'Username cannot be empty' };
126
+ }
127
+ if (cleaned.length > exports.MAX_LENGTHS.username) {
128
+ return { valid: false, error: `Username exceeds maximum length of ${exports.MAX_LENGTHS.username}` };
129
+ }
130
+ if (!VALID_PATTERNS.username.test(cleaned)) {
131
+ return { valid: false, error: 'Username contains invalid characters' };
132
+ }
133
+ return { valid: true, sanitized: cleaned };
134
+ }
135
+ /**
136
+ * Validate a search query
137
+ */
138
+ static validateQuery(query) {
139
+ if (typeof query !== 'string') {
140
+ return { valid: false, error: 'Search query must be a string' };
141
+ }
142
+ if (!query.trim()) {
143
+ return { valid: false, error: 'Search query cannot be empty' };
144
+ }
145
+ if (query.length > exports.MAX_LENGTHS.query) {
146
+ return { valid: false, error: `Search query exceeds maximum length of ${exports.MAX_LENGTHS.query}` };
147
+ }
148
+ // Don't check for dangerous patterns in queries as they might be searching for code
149
+ // But do sanitize for display
150
+ return { valid: true, sanitized: query.trim() };
151
+ }
152
+ /**
153
+ * Validate message text
154
+ */
155
+ static validateMessageText(text) {
156
+ if (typeof text !== 'string') {
157
+ return { valid: false, error: 'Message text must be a string' };
158
+ }
159
+ if (!text.trim()) {
160
+ return { valid: false, error: 'Message text cannot be empty' };
161
+ }
162
+ if (text.length > exports.MAX_LENGTHS.messageText) {
163
+ return { valid: false, error: `Message text exceeds maximum length of ${exports.MAX_LENGTHS.messageText}` };
164
+ }
165
+ return { valid: true, sanitized: text };
166
+ }
167
+ /**
168
+ * Validate an emoji
169
+ */
170
+ static validateEmoji(emoji) {
171
+ if (typeof emoji !== 'string') {
172
+ return { valid: false, error: 'Emoji must be a string' };
173
+ }
174
+ const cleaned = emoji.trim();
175
+ if (!cleaned) {
176
+ return { valid: false, error: 'Emoji cannot be empty' };
177
+ }
178
+ if (cleaned.length > exports.MAX_LENGTHS.emoji) {
179
+ return { valid: false, error: `Emoji exceeds maximum length of ${exports.MAX_LENGTHS.emoji}` };
180
+ }
181
+ if (!VALID_PATTERNS.emoji.test(cleaned)) {
182
+ return { valid: false, error: 'Emoji contains invalid characters' };
183
+ }
184
+ return { valid: true, sanitized: cleaned };
185
+ }
186
+ /**
187
+ * Validate pagination limit
188
+ */
189
+ static validateLimit(limit, min = 1, max = 100, defaultValue = 50) {
190
+ if (limit === undefined || limit === null) {
191
+ return defaultValue;
192
+ }
193
+ const num = Number(limit);
194
+ if (isNaN(num)) {
195
+ return defaultValue;
196
+ }
197
+ return Math.max(min, Math.min(max, Math.floor(num)));
198
+ }
199
+ /**
200
+ * Validate pagination offset
201
+ */
202
+ static validateOffset(offset, defaultValue = 0) {
203
+ if (offset === undefined || offset === null) {
204
+ return defaultValue;
205
+ }
206
+ const num = Number(offset);
207
+ if (isNaN(num) || num < 0) {
208
+ return defaultValue;
209
+ }
210
+ return Math.floor(num);
211
+ }
212
+ /**
213
+ * Check if string contains dangerous patterns
214
+ */
215
+ static containsDangerousPattern(input) {
216
+ return DANGEROUS_PATTERNS.some(pattern => pattern.test(input));
217
+ }
218
+ /**
219
+ * Escape HTML entities for safe display
220
+ */
221
+ static escapeHtml(text) {
222
+ const htmlEntities = {
223
+ '&': '&amp;',
224
+ '<': '&lt;',
225
+ '>': '&gt;',
226
+ '"': '&quot;',
227
+ "'": '&#x27;',
228
+ };
229
+ return text.replace(/[&<>"']/g, char => htmlEntities[char] || char);
230
+ }
231
+ /**
232
+ * Validate and sanitize a generic string input
233
+ */
234
+ static validateString(value, fieldName, maxLength, required = true) {
235
+ if (value === undefined || value === null) {
236
+ if (required) {
237
+ return { valid: false, error: `${fieldName} is required` };
238
+ }
239
+ return { valid: true };
240
+ }
241
+ if (typeof value !== 'string') {
242
+ return { valid: false, error: `${fieldName} must be a string` };
243
+ }
244
+ const trimmed = value.trim();
245
+ if (required && !trimmed) {
246
+ return { valid: false, error: `${fieldName} cannot be empty` };
247
+ }
248
+ if (trimmed.length > maxLength) {
249
+ return { valid: false, error: `${fieldName} exceeds maximum length of ${maxLength}` };
250
+ }
251
+ return { valid: true, sanitized: trimmed };
252
+ }
253
+ }
254
+ exports.InputValidator = InputValidator;
255
+ // Export singleton-like utility functions
256
+ exports.validateRoomId = InputValidator.validateRoomId.bind(InputValidator);
257
+ exports.validateMessageId = InputValidator.validateMessageId.bind(InputValidator);
258
+ exports.validateUserId = InputValidator.validateUserId.bind(InputValidator);
259
+ exports.validateUsername = InputValidator.validateUsername.bind(InputValidator);
260
+ exports.validateQuery = InputValidator.validateQuery.bind(InputValidator);
261
+ exports.validateMessageText = InputValidator.validateMessageText.bind(InputValidator);
262
+ exports.validateEmoji = InputValidator.validateEmoji.bind(InputValidator);
263
+ exports.validateLimit = InputValidator.validateLimit.bind(InputValidator);
264
+ exports.validateOffset = InputValidator.validateOffset.bind(InputValidator);
265
+ exports.escapeHtml = InputValidator.escapeHtml.bind(InputValidator);
266
+ //# sourceMappingURL=input-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-validator.js","sourceRoot":"","sources":["../../src/guards/input-validator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Rate Limiter - Prevents excessive API calls
3
+ * Uses a sliding window algorithm for rate limiting
4
+ */
5
+ /**
6
+ * Rate limit configuration
7
+ */
8
+ export interface RateLimitConfig {
9
+ /** Maximum number of requests allowed in the window */
10
+ maxRequests: number;
11
+ /** Window size in milliseconds */
12
+ windowMs: number;
13
+ /** Optional key prefix for namespacing */
14
+ keyPrefix?: string;
15
+ }
16
+ /**
17
+ * Rate limit check result
18
+ */
19
+ export interface RateLimitResult {
20
+ allowed: boolean;
21
+ remaining: number;
22
+ resetAt: number;
23
+ retryAfterMs?: number;
24
+ }
25
+ /**
26
+ * Default rate limit configurations
27
+ */
28
+ export declare const DEFAULT_LIMITS: {
29
+ /** General API calls */
30
+ readonly api: {
31
+ readonly maxRequests: 100;
32
+ readonly windowMs: 60000;
33
+ };
34
+ /** Write operations (send message, react) */
35
+ readonly write: {
36
+ readonly maxRequests: 20;
37
+ readonly windowMs: 60000;
38
+ };
39
+ /** Search operations */
40
+ readonly search: {
41
+ readonly maxRequests: 30;
42
+ readonly windowMs: 60000;
43
+ };
44
+ /** Heavy operations (list all, bulk operations) */
45
+ readonly heavy: {
46
+ readonly maxRequests: 10;
47
+ readonly windowMs: 60000;
48
+ };
49
+ };
50
+ /**
51
+ * Rate limiter class with sliding window algorithm
52
+ */
53
+ export declare class RateLimiter {
54
+ private records;
55
+ private config;
56
+ private cleanupInterval;
57
+ constructor(config: RateLimitConfig);
58
+ /**
59
+ * Check if a request is allowed and record it
60
+ */
61
+ check(key: string): RateLimitResult;
62
+ /**
63
+ * Check without recording (peek)
64
+ */
65
+ peek(key: string): RateLimitResult;
66
+ /**
67
+ * Reset rate limit for a key
68
+ */
69
+ reset(key: string): void;
70
+ /**
71
+ * Reset all rate limits
72
+ */
73
+ resetAll(): void;
74
+ /**
75
+ * Get current configuration
76
+ */
77
+ getConfig(): RateLimitConfig;
78
+ /**
79
+ * Clean up old records
80
+ */
81
+ private cleanup;
82
+ /**
83
+ * Stop the cleanup interval
84
+ */
85
+ destroy(): void;
86
+ }
87
+ /**
88
+ * Rate limiter manager for multiple rate limit types
89
+ */
90
+ export declare class RateLimiterManager {
91
+ private limiters;
92
+ /**
93
+ * Get or create a rate limiter
94
+ */
95
+ getLimiter(name: string, config?: RateLimitConfig): RateLimiter;
96
+ /**
97
+ * Check rate limit for a specific limiter type
98
+ */
99
+ check(limiterName: string, key: string): RateLimitResult;
100
+ /**
101
+ * Reset all limiters
102
+ */
103
+ resetAll(): void;
104
+ /**
105
+ * Destroy all limiters
106
+ */
107
+ destroy(): void;
108
+ }
109
+ export declare function getRateLimiterManager(): RateLimiterManager;
110
+ export declare function resetRateLimiterManager(): void;
111
+ export declare function checkRateLimit(limiterName: string, key: string): RateLimitResult;
112
+ export declare function checkApiRateLimit(key: string): RateLimitResult;
113
+ export declare function checkWriteRateLimit(key: string): RateLimitResult;
114
+ export declare function checkSearchRateLimit(key: string): RateLimitResult;
115
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/guards/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,eAAO,MAAM,cAAc;IACvB,wBAAwB;;;;;IAExB,6CAA6C;;;;;IAE7C,wBAAwB;;;;;IAExB,mDAAmD;;;;;CAE7C,CAAC;AASX;;GAEG;AACH,qBAAa,WAAW;IACpB,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,eAAe,CAA+B;gBAE1C,MAAM,EAAE,eAAe;IAOnC;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IAgDnC;;OAEG;IACH,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe;IA6BlC;;OAEG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKxB;;OAEG;IACH,QAAQ,IAAI,IAAI;IAIhB;;OAEG;IACH,SAAS,IAAI,eAAe;IAI5B;;OAEG;IACH,OAAO,CAAC,OAAO;IAYf;;OAEG;IACH,OAAO,IAAI,IAAI;CAOlB;AAED;;GAEG;AACH,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAuC;IAEvD;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,WAAW;IAW/D;;OAEG;IACH,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe;IAKxD;;OAEG;IACH,QAAQ,IAAI,IAAI;IAMhB;;OAEG;IACH,OAAO,IAAI,IAAI;CAMlB;AAKD,wBAAgB,qBAAqB,IAAI,kBAAkB,CAK1D;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAK9C;AAGD,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,eAAe,CAEhF;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAE9D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAEhE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAEjE"}
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ /**
3
+ * Rate Limiter - Prevents excessive API calls
4
+ * Uses a sliding window algorithm for rate limiting
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.RateLimiterManager = exports.RateLimiter = exports.DEFAULT_LIMITS = void 0;
8
+ exports.getRateLimiterManager = getRateLimiterManager;
9
+ exports.resetRateLimiterManager = resetRateLimiterManager;
10
+ exports.checkRateLimit = checkRateLimit;
11
+ exports.checkApiRateLimit = checkApiRateLimit;
12
+ exports.checkWriteRateLimit = checkWriteRateLimit;
13
+ exports.checkSearchRateLimit = checkSearchRateLimit;
14
+ const logger_js_1 = require("../utils/logger.js");
15
+ const logger = (0, logger_js_1.getLogger)('RateLimiter');
16
+ /**
17
+ * Default rate limit configurations
18
+ */
19
+ exports.DEFAULT_LIMITS = {
20
+ /** General API calls */
21
+ api: { maxRequests: 100, windowMs: 60000 },
22
+ /** Write operations (send message, react) */
23
+ write: { maxRequests: 20, windowMs: 60000 },
24
+ /** Search operations */
25
+ search: { maxRequests: 30, windowMs: 60000 },
26
+ /** Heavy operations (list all, bulk operations) */
27
+ heavy: { maxRequests: 10, windowMs: 60000 },
28
+ };
29
+ /**
30
+ * Rate limiter class with sliding window algorithm
31
+ */
32
+ class RateLimiter {
33
+ records = new Map();
34
+ config;
35
+ cleanupInterval = null;
36
+ constructor(config) {
37
+ this.config = config;
38
+ // Cleanup old records every minute
39
+ this.cleanupInterval = setInterval(() => this.cleanup(), 60000);
40
+ }
41
+ /**
42
+ * Check if a request is allowed and record it
43
+ */
44
+ check(key) {
45
+ const fullKey = this.config.keyPrefix ? `${this.config.keyPrefix}:${key}` : key;
46
+ const now = Date.now();
47
+ const windowStart = now - this.config.windowMs;
48
+ // Get or create record
49
+ let record = this.records.get(fullKey);
50
+ if (!record) {
51
+ record = { timestamps: [] };
52
+ this.records.set(fullKey, record);
53
+ }
54
+ // Remove timestamps outside the window
55
+ record.timestamps = record.timestamps.filter(ts => ts > windowStart);
56
+ const currentCount = record.timestamps.length;
57
+ const remaining = Math.max(0, this.config.maxRequests - currentCount);
58
+ const resetAt = record.timestamps.length > 0
59
+ ? record.timestamps[0] + this.config.windowMs
60
+ : now + this.config.windowMs;
61
+ if (currentCount >= this.config.maxRequests) {
62
+ const retryAfterMs = resetAt - now;
63
+ logger.debug('Rate limit exceeded', {
64
+ key: fullKey,
65
+ currentCount,
66
+ maxRequests: this.config.maxRequests,
67
+ retryAfterMs
68
+ });
69
+ return {
70
+ allowed: false,
71
+ remaining: 0,
72
+ resetAt,
73
+ retryAfterMs
74
+ };
75
+ }
76
+ // Record this request
77
+ record.timestamps.push(now);
78
+ return {
79
+ allowed: true,
80
+ remaining: remaining - 1,
81
+ resetAt
82
+ };
83
+ }
84
+ /**
85
+ * Check without recording (peek)
86
+ */
87
+ peek(key) {
88
+ const fullKey = this.config.keyPrefix ? `${this.config.keyPrefix}:${key}` : key;
89
+ const now = Date.now();
90
+ const windowStart = now - this.config.windowMs;
91
+ const record = this.records.get(fullKey);
92
+ if (!record) {
93
+ return {
94
+ allowed: true,
95
+ remaining: this.config.maxRequests,
96
+ resetAt: now + this.config.windowMs
97
+ };
98
+ }
99
+ const validTimestamps = record.timestamps.filter(ts => ts > windowStart);
100
+ const currentCount = validTimestamps.length;
101
+ const remaining = Math.max(0, this.config.maxRequests - currentCount);
102
+ const resetAt = validTimestamps.length > 0
103
+ ? validTimestamps[0] + this.config.windowMs
104
+ : now + this.config.windowMs;
105
+ return {
106
+ allowed: currentCount < this.config.maxRequests,
107
+ remaining,
108
+ resetAt,
109
+ retryAfterMs: currentCount >= this.config.maxRequests ? resetAt - now : undefined
110
+ };
111
+ }
112
+ /**
113
+ * Reset rate limit for a key
114
+ */
115
+ reset(key) {
116
+ const fullKey = this.config.keyPrefix ? `${this.config.keyPrefix}:${key}` : key;
117
+ this.records.delete(fullKey);
118
+ }
119
+ /**
120
+ * Reset all rate limits
121
+ */
122
+ resetAll() {
123
+ this.records.clear();
124
+ }
125
+ /**
126
+ * Get current configuration
127
+ */
128
+ getConfig() {
129
+ return { ...this.config };
130
+ }
131
+ /**
132
+ * Clean up old records
133
+ */
134
+ cleanup() {
135
+ const now = Date.now();
136
+ const windowStart = now - this.config.windowMs;
137
+ for (const [key, record] of this.records.entries()) {
138
+ record.timestamps = record.timestamps.filter(ts => ts > windowStart);
139
+ if (record.timestamps.length === 0) {
140
+ this.records.delete(key);
141
+ }
142
+ }
143
+ }
144
+ /**
145
+ * Stop the cleanup interval
146
+ */
147
+ destroy() {
148
+ if (this.cleanupInterval) {
149
+ clearInterval(this.cleanupInterval);
150
+ this.cleanupInterval = null;
151
+ }
152
+ this.records.clear();
153
+ }
154
+ }
155
+ exports.RateLimiter = RateLimiter;
156
+ /**
157
+ * Rate limiter manager for multiple rate limit types
158
+ */
159
+ class RateLimiterManager {
160
+ limiters = new Map();
161
+ /**
162
+ * Get or create a rate limiter
163
+ */
164
+ getLimiter(name, config) {
165
+ if (this.limiters.has(name)) {
166
+ return this.limiters.get(name);
167
+ }
168
+ const limiterConfig = config || exports.DEFAULT_LIMITS[name] || exports.DEFAULT_LIMITS.api;
169
+ const limiter = new RateLimiter({ ...limiterConfig, keyPrefix: name });
170
+ this.limiters.set(name, limiter);
171
+ return limiter;
172
+ }
173
+ /**
174
+ * Check rate limit for a specific limiter type
175
+ */
176
+ check(limiterName, key) {
177
+ const limiter = this.getLimiter(limiterName);
178
+ return limiter.check(key);
179
+ }
180
+ /**
181
+ * Reset all limiters
182
+ */
183
+ resetAll() {
184
+ for (const limiter of this.limiters.values()) {
185
+ limiter.resetAll();
186
+ }
187
+ }
188
+ /**
189
+ * Destroy all limiters
190
+ */
191
+ destroy() {
192
+ for (const limiter of this.limiters.values()) {
193
+ limiter.destroy();
194
+ }
195
+ this.limiters.clear();
196
+ }
197
+ }
198
+ exports.RateLimiterManager = RateLimiterManager;
199
+ // Singleton instance
200
+ let managerInstance = null;
201
+ function getRateLimiterManager() {
202
+ if (!managerInstance) {
203
+ managerInstance = new RateLimiterManager();
204
+ }
205
+ return managerInstance;
206
+ }
207
+ function resetRateLimiterManager() {
208
+ if (managerInstance) {
209
+ managerInstance.destroy();
210
+ managerInstance = null;
211
+ }
212
+ }
213
+ // Convenience functions
214
+ function checkRateLimit(limiterName, key) {
215
+ return getRateLimiterManager().check(limiterName, key);
216
+ }
217
+ function checkApiRateLimit(key) {
218
+ return getRateLimiterManager().check('api', key);
219
+ }
220
+ function checkWriteRateLimit(key) {
221
+ return getRateLimiterManager().check('write', key);
222
+ }
223
+ function checkSearchRateLimit(key) {
224
+ return getRateLimiterManager().check('search', key);
225
+ }
226
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/guards/rate-limiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Message Sanitizer - Neutralizes dangerous mentions and patterns
3
+ * Prevents accidental mass notifications (@all, @here, @channel)
4
+ */
5
+ export interface SanitizeResult {
6
+ text: string;
7
+ modified: boolean;
8
+ neutralized: string[];
9
+ }
10
+ export declare class MessageSanitizer {
11
+ private blockMentions;
12
+ private blockedMentions;
13
+ constructor();
14
+ /**
15
+ * Sanitize message text
16
+ */
17
+ sanitize(text: string): SanitizeResult;
18
+ /**
19
+ * Check if text contains dangerous patterns without modifying
20
+ */
21
+ check(text: string): {
22
+ hasDangerousPatterns: boolean;
23
+ patterns: string[];
24
+ };
25
+ /**
26
+ * Get current configuration
27
+ */
28
+ getConfig(): {
29
+ blockMentions: boolean;
30
+ blockedMentions: string[];
31
+ };
32
+ }
33
+ export declare function getSanitizer(): MessageSanitizer;
34
+ export declare function resetSanitizer(): void;
35
+ //# sourceMappingURL=sanitizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizer.d.ts","sourceRoot":"","sources":["../../src/guards/sanitizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,cAAc;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;CACzB;AAkBD,qBAAa,gBAAgB;IACzB,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,eAAe,CAAW;;IAQlC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc;IAmCtC;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,oBAAoB,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE;IAuB1E;;OAEG;IACH,SAAS,IAAI;QAAE,aAAa,EAAE,OAAO,CAAC;QAAC,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE;CAMrE;AAKD,wBAAgB,YAAY,IAAI,gBAAgB,CAK/C;AAED,wBAAgB,cAAc,IAAI,IAAI,CAErC"}