telegram-ssh-bot 2.0.0 → 2.2.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.
- package/LICENSE +21 -0
- package/README.md +103 -22
- package/deploy/.env.example +86 -0
- package/dist/config/index.d.ts +68 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +315 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +6 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +50 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/Bot.d.ts +91 -0
- package/dist/core/Bot.d.ts.map +1 -0
- package/dist/core/Bot.js +263 -0
- package/dist/core/Bot.js.map +1 -0
- package/dist/core/ConnectionPool.d.ts +125 -0
- package/dist/core/ConnectionPool.d.ts.map +1 -0
- package/dist/core/ConnectionPool.js +397 -0
- package/dist/core/ConnectionPool.js.map +1 -0
- package/dist/core/SSHClient.d.ts +112 -0
- package/dist/core/SSHClient.d.ts.map +1 -0
- package/dist/core/SSHClient.js +367 -0
- package/dist/core/SSHClient.js.map +1 -0
- package/dist/core/ServerManager.d.ts +80 -0
- package/dist/core/ServerManager.d.ts.map +1 -0
- package/dist/core/ServerManager.js +207 -0
- package/dist/core/ServerManager.js.map +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +8 -0
- package/dist/core/index.js.map +1 -0
- package/dist/errors/AuthError.d.ts +30 -0
- package/dist/errors/AuthError.d.ts.map +1 -0
- package/dist/errors/AuthError.js +35 -0
- package/dist/errors/AuthError.js.map +1 -0
- package/dist/errors/BaseError.d.ts +17 -0
- package/dist/errors/BaseError.d.ts.map +1 -0
- package/dist/errors/BaseError.js +34 -0
- package/dist/errors/BaseError.js.map +1 -0
- package/dist/errors/ConfigurationError.d.ts +24 -0
- package/dist/errors/ConfigurationError.d.ts.map +1 -0
- package/dist/errors/ConfigurationError.js +24 -0
- package/dist/errors/ConfigurationError.js.map +1 -0
- package/dist/errors/PoolError.d.ts +21 -0
- package/dist/errors/PoolError.d.ts.map +1 -0
- package/dist/errors/PoolError.js +30 -0
- package/dist/errors/PoolError.js.map +1 -0
- package/dist/errors/SSHError.d.ts +24 -0
- package/dist/errors/SSHError.d.ts.map +1 -0
- package/dist/errors/SSHError.js +38 -0
- package/dist/errors/SSHError.js.map +1 -0
- package/dist/errors/StorageError.d.ts +24 -0
- package/dist/errors/StorageError.d.ts.map +1 -0
- package/dist/errors/StorageError.js +35 -0
- package/dist/errors/StorageError.js.map +1 -0
- package/dist/errors/ValidationError.d.ts +29 -0
- package/dist/errors/ValidationError.d.ts.map +1 -0
- package/dist/errors/ValidationError.js +35 -0
- package/dist/errors/ValidationError.js.map +1 -0
- package/dist/errors/index.d.ts +11 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +18 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/handlers/BaseHandler.d.ts +50 -0
- package/dist/handlers/BaseHandler.d.ts.map +1 -0
- package/dist/handlers/BaseHandler.js +87 -0
- package/dist/handlers/BaseHandler.js.map +1 -0
- package/dist/handlers/CommandHandler.d.ts +23 -0
- package/dist/handlers/CommandHandler.d.ts.map +1 -0
- package/dist/handlers/CommandHandler.js +99 -0
- package/dist/handlers/CommandHandler.js.map +1 -0
- package/dist/handlers/HealthHandler.d.ts +25 -0
- package/dist/handlers/HealthHandler.d.ts.map +1 -0
- package/dist/handlers/HealthHandler.js +51 -0
- package/dist/handlers/HealthHandler.js.map +1 -0
- package/dist/handlers/HelpHandler.d.ts +32 -0
- package/dist/handlers/HelpHandler.d.ts.map +1 -0
- package/dist/handlers/HelpHandler.js +76 -0
- package/dist/handlers/HelpHandler.js.map +1 -0
- package/dist/handlers/ServerHandler.d.ts +72 -0
- package/dist/handlers/ServerHandler.d.ts.map +1 -0
- package/dist/handlers/ServerHandler.js +272 -0
- package/dist/handlers/ServerHandler.js.map +1 -0
- package/dist/handlers/index.d.ts +9 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +9 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +348 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/AuthMiddleware.d.ts +28 -0
- package/dist/middleware/AuthMiddleware.d.ts.map +1 -0
- package/dist/middleware/AuthMiddleware.js +49 -0
- package/dist/middleware/AuthMiddleware.js.map +1 -0
- package/dist/middleware/RateLimitMiddleware.d.ts +23 -0
- package/dist/middleware/RateLimitMiddleware.d.ts.map +1 -0
- package/dist/middleware/RateLimitMiddleware.js +34 -0
- package/dist/middleware/RateLimitMiddleware.js.map +1 -0
- package/dist/middleware/index.d.ts +6 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +6 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/services/BackupService.d.ts +119 -0
- package/dist/services/BackupService.d.ts.map +1 -0
- package/dist/services/BackupService.js +313 -0
- package/dist/services/BackupService.js.map +1 -0
- package/dist/services/CryptoService.d.ts +37 -0
- package/dist/services/CryptoService.d.ts.map +1 -0
- package/dist/services/CryptoService.js +108 -0
- package/dist/services/CryptoService.js.map +1 -0
- package/dist/services/HealthService.d.ts +126 -0
- package/dist/services/HealthService.d.ts.map +1 -0
- package/dist/services/HealthService.js +213 -0
- package/dist/services/HealthService.js.map +1 -0
- package/dist/services/LoggingService.d.ts +115 -0
- package/dist/services/LoggingService.d.ts.map +1 -0
- package/dist/services/LoggingService.js +334 -0
- package/dist/services/LoggingService.js.map +1 -0
- package/dist/services/MonitoringService.d.ts +119 -0
- package/dist/services/MonitoringService.d.ts.map +1 -0
- package/dist/services/MonitoringService.js +267 -0
- package/dist/services/MonitoringService.js.map +1 -0
- package/dist/services/NotificationService.d.ts +132 -0
- package/dist/services/NotificationService.d.ts.map +1 -0
- package/dist/services/NotificationService.js +297 -0
- package/dist/services/NotificationService.js.map +1 -0
- package/dist/services/RateLimiter.d.ts +51 -0
- package/dist/services/RateLimiter.d.ts.map +1 -0
- package/dist/services/RateLimiter.js +141 -0
- package/dist/services/RateLimiter.js.map +1 -0
- package/dist/services/ValidationService.d.ts +49 -0
- package/dist/services/ValidationService.d.ts.map +1 -0
- package/dist/services/ValidationService.js +158 -0
- package/dist/services/ValidationService.js.map +1 -0
- package/dist/services/index.d.ts +12 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +12 -0
- package/dist/services/index.js.map +1 -0
- package/dist/types/Bot.d.ts +63 -0
- package/dist/types/Bot.d.ts.map +1 -0
- package/dist/types/Bot.js +5 -0
- package/dist/types/Bot.js.map +1 -0
- package/dist/types/Config.d.ts +57 -0
- package/dist/types/Config.d.ts.map +1 -0
- package/dist/types/Config.js +5 -0
- package/dist/types/Config.js.map +1 -0
- package/dist/types/Errors.d.ts +37 -0
- package/dist/types/Errors.d.ts.map +1 -0
- package/dist/types/Errors.js +34 -0
- package/dist/types/Errors.js.map +1 -0
- package/dist/types/SSH.d.ts +56 -0
- package/dist/types/SSH.d.ts.map +1 -0
- package/dist/types/SSH.js +6 -0
- package/dist/types/SSH.js.map +1 -0
- package/dist/types/Server.d.ts +39 -0
- package/dist/types/Server.d.ts.map +1 -0
- package/dist/types/Server.js +5 -0
- package/dist/types/Server.js.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/commandUtils.d.ts +25 -0
- package/dist/utils/commandUtils.d.ts.map +1 -0
- package/dist/utils/commandUtils.js +94 -0
- package/dist/utils/commandUtils.js.map +1 -0
- package/dist/utils/fileUtils.d.ts +40 -0
- package/dist/utils/fileUtils.d.ts.map +1 -0
- package/dist/utils/fileUtils.js +114 -0
- package/dist/utils/fileUtils.js.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/pathUtils.d.ts +40 -0
- package/dist/utils/pathUtils.d.ts.map +1 -0
- package/dist/utils/pathUtils.js +140 -0
- package/dist/utils/pathUtils.js.map +1 -0
- package/package.json +31 -5
- package/scripts/build.sh +20 -0
- package/scripts/postinstall.js +87 -0
- package/scripts/release.sh +22 -0
- package/scripts/setup-env.js +237 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification Service
|
|
3
|
+
* Provides admin notifications for important events
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Service for sending admin notifications
|
|
7
|
+
*/
|
|
8
|
+
export class NotificationService {
|
|
9
|
+
logger;
|
|
10
|
+
config;
|
|
11
|
+
bot = null;
|
|
12
|
+
notificationCount = 0;
|
|
13
|
+
startTime;
|
|
14
|
+
constructor(config, logger) {
|
|
15
|
+
this.config = {
|
|
16
|
+
enabled: config.enabled ?? true,
|
|
17
|
+
notifyOnStartup: config.notifyOnStartup ?? true,
|
|
18
|
+
notifyOnShutdown: config.notifyOnShutdown ?? true,
|
|
19
|
+
notifyOnErrors: config.notifyOnErrors ?? true,
|
|
20
|
+
notifyOnSecurity: config.notifyOnSecurity ?? true,
|
|
21
|
+
adminChatId: config.adminChatId ?? "",
|
|
22
|
+
};
|
|
23
|
+
this.logger = logger;
|
|
24
|
+
this.startTime = new Date();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Set the bot instance for sending messages
|
|
28
|
+
*/
|
|
29
|
+
setBot(bot) {
|
|
30
|
+
this.bot = bot;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Send a notification
|
|
34
|
+
*/
|
|
35
|
+
async notify(payload) {
|
|
36
|
+
if (!this.config.enabled || !this.bot || !this.config.adminChatId) {
|
|
37
|
+
this.logger.debug("Notification skipped", {
|
|
38
|
+
enabled: this.config.enabled,
|
|
39
|
+
hasBot: !!this.bot,
|
|
40
|
+
hasChatId: !!this.config.adminChatId,
|
|
41
|
+
});
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const fullPayload = {
|
|
45
|
+
...payload,
|
|
46
|
+
timestamp: new Date(),
|
|
47
|
+
};
|
|
48
|
+
try {
|
|
49
|
+
const message = this.formatNotification(fullPayload);
|
|
50
|
+
await this.bot.sendMessage(parseInt(this.config.adminChatId, 10), message, { parseMode: "Markdown" });
|
|
51
|
+
this.notificationCount++;
|
|
52
|
+
this.logger.debug("Notification sent", {
|
|
53
|
+
type: payload.type,
|
|
54
|
+
priority: payload.priority,
|
|
55
|
+
});
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
this.logger.error("Failed to send notification", error, {
|
|
60
|
+
type: payload.type,
|
|
61
|
+
});
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Send startup notification
|
|
67
|
+
*/
|
|
68
|
+
async notifyStartup(version) {
|
|
69
|
+
if (!this.config.notifyOnStartup) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return this.notify({
|
|
73
|
+
type: "startup",
|
|
74
|
+
priority: "normal",
|
|
75
|
+
title: "🚀 Bot Started",
|
|
76
|
+
message: `Telegram SSH Bot has started successfully.\n\nVersion: ${version}\nStarted at: ${this.startTime.toISOString()}`,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Send shutdown notification
|
|
81
|
+
*/
|
|
82
|
+
async notifyShutdown(reason) {
|
|
83
|
+
if (!this.config.notifyOnShutdown) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const uptime = Math.floor((Date.now() - this.startTime.getTime()) / 1000);
|
|
87
|
+
return this.notify({
|
|
88
|
+
type: "shutdown",
|
|
89
|
+
priority: "high",
|
|
90
|
+
title: "🛑 Bot Shutting Down",
|
|
91
|
+
message: `Telegram SSH Bot is shutting down.\n\nReason: ${reason}\nUptime: ${this.formatUptime(uptime)}`,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Send error notification
|
|
96
|
+
*/
|
|
97
|
+
async notifyError(error, context) {
|
|
98
|
+
if (!this.config.notifyOnErrors) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
return this.notify({
|
|
102
|
+
type: "error",
|
|
103
|
+
priority: "high",
|
|
104
|
+
title: "⚠️ Error Occurred",
|
|
105
|
+
message: `An error occurred:\n\n${error.message}\n\nStack: \`${error.stack?.split("\n")[0] ?? "N/A"}\``,
|
|
106
|
+
details: { errorName: error.name, ...context },
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Send security notification
|
|
111
|
+
*/
|
|
112
|
+
async notifySecurity(event, details) {
|
|
113
|
+
if (!this.config.notifyOnSecurity) {
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
return this.notify({
|
|
117
|
+
type: "security",
|
|
118
|
+
priority: "critical",
|
|
119
|
+
title: "🔒 Security Event",
|
|
120
|
+
message: `Security event detected:\n\n${event}`,
|
|
121
|
+
details,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Send server added notification
|
|
126
|
+
*/
|
|
127
|
+
async notifyServerAdded(server) {
|
|
128
|
+
return this.notify({
|
|
129
|
+
type: "server_added",
|
|
130
|
+
priority: "normal",
|
|
131
|
+
title: "➕ Server Added",
|
|
132
|
+
message: `New server added:\n\nHost: \`${server.host}\`\nUsername: \`${server.username}\`\nPort: ${server.port}`,
|
|
133
|
+
details: { serverId: server.id },
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Send server removed notification
|
|
138
|
+
*/
|
|
139
|
+
async notifyServerRemoved(server) {
|
|
140
|
+
return this.notify({
|
|
141
|
+
type: "server_removed",
|
|
142
|
+
priority: "normal",
|
|
143
|
+
title: "➖ Server Removed",
|
|
144
|
+
message: `Server removed:\n\nHost: \`${server.host}\`\nUsername: \`${server.username}\``,
|
|
145
|
+
details: { serverId: server.id },
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Send connection lost notification
|
|
150
|
+
*/
|
|
151
|
+
async notifyConnectionLost(server, error) {
|
|
152
|
+
return this.notify({
|
|
153
|
+
type: "connection_lost",
|
|
154
|
+
priority: "high",
|
|
155
|
+
title: "🔌 Connection Lost",
|
|
156
|
+
message: `Connection lost to server:\n\nHost: \`${server.host}\`\n${error ? `Error: ${error}` : ""}`,
|
|
157
|
+
details: { serverId: server.id, error },
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Send connection restored notification
|
|
162
|
+
*/
|
|
163
|
+
async notifyConnectionRestored(server) {
|
|
164
|
+
return this.notify({
|
|
165
|
+
type: "connection_restored",
|
|
166
|
+
priority: "normal",
|
|
167
|
+
title: "✅ Connection Restored",
|
|
168
|
+
message: `Connection restored to server:\n\nHost: \`${server.host}\``,
|
|
169
|
+
details: { serverId: server.id },
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Send backup created notification
|
|
174
|
+
*/
|
|
175
|
+
async notifyBackupCreated(backupId, size) {
|
|
176
|
+
return this.notify({
|
|
177
|
+
type: "backup_created",
|
|
178
|
+
priority: "low",
|
|
179
|
+
title: "💾 Backup Created",
|
|
180
|
+
message: `Backup created successfully.\n\nID: \`${backupId}\`\nSize: ${this.formatBytes(size)}`,
|
|
181
|
+
details: { backupId, size },
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Send backup restored notification
|
|
186
|
+
*/
|
|
187
|
+
async notifyBackupRestored(backupId) {
|
|
188
|
+
return this.notify({
|
|
189
|
+
type: "backup_restored",
|
|
190
|
+
priority: "normal",
|
|
191
|
+
title: "📂 Backup Restored",
|
|
192
|
+
message: `Backup restored successfully.\n\nID: \`${backupId}\``,
|
|
193
|
+
details: { backupId },
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Send config reloaded notification
|
|
198
|
+
*/
|
|
199
|
+
async notifyConfigReloaded(success) {
|
|
200
|
+
return this.notify({
|
|
201
|
+
type: "config_reloaded",
|
|
202
|
+
priority: success ? "normal" : "high",
|
|
203
|
+
title: success ? "⚙️ Config Reloaded" : "⚠️ Config Reload Failed",
|
|
204
|
+
message: success
|
|
205
|
+
? "Configuration reloaded successfully."
|
|
206
|
+
: "Configuration reload failed. Check logs for details.",
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Send rate limited notification
|
|
211
|
+
*/
|
|
212
|
+
async notifyRateLimited(chatId, command) {
|
|
213
|
+
return this.notify({
|
|
214
|
+
type: "rate_limited",
|
|
215
|
+
priority: "normal",
|
|
216
|
+
title: "⏱️ Rate Limited",
|
|
217
|
+
message: `User rate limited.\n\nChat ID: ${chatId}\nCommand: \`${command}\``,
|
|
218
|
+
details: { chatId, command },
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Send unauthorized access notification
|
|
223
|
+
*/
|
|
224
|
+
async notifyUnauthorizedAccess(chatId, username, command) {
|
|
225
|
+
return this.notify({
|
|
226
|
+
type: "unauthorized_access",
|
|
227
|
+
priority: "critical",
|
|
228
|
+
title: "🚫 Unauthorized Access",
|
|
229
|
+
message: `Unauthorized access attempt.\n\nChat ID: ${chatId}\nUsername: ${username ?? "Unknown"}\nCommand: \`${command}\``,
|
|
230
|
+
details: { chatId, username, command },
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get notification statistics
|
|
235
|
+
*/
|
|
236
|
+
getStats() {
|
|
237
|
+
return {
|
|
238
|
+
enabled: this.config.enabled,
|
|
239
|
+
totalNotifications: this.notificationCount,
|
|
240
|
+
uptime: Math.floor((Date.now() - this.startTime.getTime()) / 1000),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get log context for notification-related logs
|
|
245
|
+
*/
|
|
246
|
+
getLogContext() {
|
|
247
|
+
const stats = this.getStats();
|
|
248
|
+
return {
|
|
249
|
+
notificationsEnabled: stats.enabled,
|
|
250
|
+
totalNotifications: stats.totalNotifications,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Format notification message
|
|
255
|
+
*/
|
|
256
|
+
formatNotification(payload) {
|
|
257
|
+
const priorityEmoji = {
|
|
258
|
+
low: "ℹ️",
|
|
259
|
+
normal: "📢",
|
|
260
|
+
high: "⚠️",
|
|
261
|
+
critical: "🚨",
|
|
262
|
+
};
|
|
263
|
+
let message = `${priorityEmoji[payload.priority]} *${payload.title}*\n\n`;
|
|
264
|
+
message += payload.message;
|
|
265
|
+
message += `\n\n_Time: ${payload.timestamp.toISOString()}_`;
|
|
266
|
+
return message;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Format uptime as human-readable string
|
|
270
|
+
*/
|
|
271
|
+
formatUptime(seconds) {
|
|
272
|
+
const days = Math.floor(seconds / 86400);
|
|
273
|
+
const hours = Math.floor((seconds % 86400) / 3600);
|
|
274
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
275
|
+
const parts = [];
|
|
276
|
+
if (days > 0)
|
|
277
|
+
parts.push(`${days}d`);
|
|
278
|
+
if (hours > 0)
|
|
279
|
+
parts.push(`${hours}h`);
|
|
280
|
+
parts.push(`${minutes}m`);
|
|
281
|
+
return parts.join(" ");
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Format bytes to human-readable string
|
|
285
|
+
*/
|
|
286
|
+
formatBytes(bytes) {
|
|
287
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
288
|
+
let value = bytes;
|
|
289
|
+
let unitIndex = 0;
|
|
290
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
291
|
+
value /= 1024;
|
|
292
|
+
unitIndex++;
|
|
293
|
+
}
|
|
294
|
+
return `${value.toFixed(2)} ${units[unitIndex]}`;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=NotificationService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotificationService.js","sourceRoot":"","sources":["../../src/services/NotificationService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter Service
|
|
3
|
+
* Provides rate limiting for API requests
|
|
4
|
+
*/
|
|
5
|
+
import type { RateLimitConfig } from "../types/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Rate limiter service for controlling request frequency
|
|
8
|
+
*/
|
|
9
|
+
export declare class RateLimiter {
|
|
10
|
+
private readonly config;
|
|
11
|
+
private readonly store;
|
|
12
|
+
private cleanupTimer;
|
|
13
|
+
private static readonly CLEANUP_INTERVAL_MS;
|
|
14
|
+
constructor(config: RateLimitConfig);
|
|
15
|
+
/**
|
|
16
|
+
* Start automatic cleanup timer
|
|
17
|
+
* Runs cleanup periodically to remove expired records
|
|
18
|
+
*/
|
|
19
|
+
startAutoCleanup(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Stop automatic cleanup timer
|
|
22
|
+
* Should be called during shutdown
|
|
23
|
+
*/
|
|
24
|
+
stopAutoCleanup(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Check if a request is allowed for the given identifier
|
|
27
|
+
* @throws RateLimitedError if rate limit is exceeded
|
|
28
|
+
*/
|
|
29
|
+
checkLimit(identifier: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Check if identifier is currently rate limited
|
|
32
|
+
*/
|
|
33
|
+
isLimited(identifier: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Get remaining requests for identifier
|
|
36
|
+
*/
|
|
37
|
+
getRemaining(identifier: string): number;
|
|
38
|
+
/**
|
|
39
|
+
* Reset rate limit for identifier
|
|
40
|
+
*/
|
|
41
|
+
reset(identifier: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Reset all rate limits
|
|
44
|
+
*/
|
|
45
|
+
resetAll(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Clean up expired records
|
|
48
|
+
*/
|
|
49
|
+
cleanup(): void;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=RateLimiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RateLimiter.d.ts","sourceRoot":"","sources":["../../src/services/RateLimiter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAWzD;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2C;IACjE,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAiB;gBAEhD,MAAM,EAAE,eAAe;IAInC;;;OAGG;IACH,gBAAgB,IAAI,IAAI;IAexB;;;OAGG;IACH,eAAe,IAAI,IAAI;IAOvB;;;OAGG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IA4CvC;;OAEG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO;IAatC;;OAEG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAcxC;;OAEG;IACH,KAAK,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,QAAQ,IAAI,IAAI;IAIhB;;OAEG;IACH,OAAO,IAAI,IAAI;CAoBhB"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter Service
|
|
3
|
+
* Provides rate limiting for API requests
|
|
4
|
+
*/
|
|
5
|
+
import { RateLimitedError } from "../errors/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Rate limiter service for controlling request frequency
|
|
8
|
+
*/
|
|
9
|
+
export class RateLimiter {
|
|
10
|
+
config;
|
|
11
|
+
store = new Map();
|
|
12
|
+
cleanupTimer = null;
|
|
13
|
+
static CLEANUP_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Start automatic cleanup timer
|
|
19
|
+
* Runs cleanup periodically to remove expired records
|
|
20
|
+
*/
|
|
21
|
+
startAutoCleanup() {
|
|
22
|
+
if (this.cleanupTimer) {
|
|
23
|
+
return; // Already running
|
|
24
|
+
}
|
|
25
|
+
this.cleanupTimer = setInterval(() => {
|
|
26
|
+
this.cleanup();
|
|
27
|
+
}, RateLimiter.CLEANUP_INTERVAL_MS);
|
|
28
|
+
// Prevent the timer from keeping the process alive
|
|
29
|
+
if (this.cleanupTimer.unref) {
|
|
30
|
+
this.cleanupTimer.unref();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Stop automatic cleanup timer
|
|
35
|
+
* Should be called during shutdown
|
|
36
|
+
*/
|
|
37
|
+
stopAutoCleanup() {
|
|
38
|
+
if (this.cleanupTimer) {
|
|
39
|
+
clearInterval(this.cleanupTimer);
|
|
40
|
+
this.cleanupTimer = null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if a request is allowed for the given identifier
|
|
45
|
+
* @throws RateLimitedError if rate limit is exceeded
|
|
46
|
+
*/
|
|
47
|
+
checkLimit(identifier) {
|
|
48
|
+
if (!this.config.enabled) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
// Get or create record
|
|
53
|
+
let record = this.store.get(identifier);
|
|
54
|
+
if (!record) {
|
|
55
|
+
record = { requests: [], blocked: false };
|
|
56
|
+
this.store.set(identifier, record);
|
|
57
|
+
}
|
|
58
|
+
// Check if blocked
|
|
59
|
+
if (record.blocked) {
|
|
60
|
+
if (record.blockedUntil && now < record.blockedUntil) {
|
|
61
|
+
const retryAfter = Math.ceil((record.blockedUntil - now) / 1000);
|
|
62
|
+
throw new RateLimitedError(retryAfter, { context: { identifier } });
|
|
63
|
+
}
|
|
64
|
+
// Reset block
|
|
65
|
+
record.blocked = false;
|
|
66
|
+
record.blockedUntil = undefined;
|
|
67
|
+
}
|
|
68
|
+
// Clean old requests
|
|
69
|
+
record.requests = record.requests.filter((time) => now - time < this.config.windowMs);
|
|
70
|
+
// Check limit
|
|
71
|
+
if (record.requests.length >= this.config.maxRequests) {
|
|
72
|
+
record.blocked = true;
|
|
73
|
+
record.blockedUntil = now + this.config.windowMs;
|
|
74
|
+
throw new RateLimitedError(Math.ceil(this.config.windowMs / 1000), {
|
|
75
|
+
context: { identifier },
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// Record request
|
|
79
|
+
record.requests.push(now);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if identifier is currently rate limited
|
|
84
|
+
*/
|
|
85
|
+
isLimited(identifier) {
|
|
86
|
+
const record = this.store.get(identifier);
|
|
87
|
+
if (!record) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
if (record.blocked && record.blockedUntil) {
|
|
91
|
+
return Date.now() < record.blockedUntil;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get remaining requests for identifier
|
|
97
|
+
*/
|
|
98
|
+
getRemaining(identifier) {
|
|
99
|
+
const record = this.store.get(identifier);
|
|
100
|
+
if (!record) {
|
|
101
|
+
return this.config.maxRequests;
|
|
102
|
+
}
|
|
103
|
+
const now = Date.now();
|
|
104
|
+
const validRequests = record.requests.filter((time) => now - time < this.config.windowMs);
|
|
105
|
+
return Math.max(0, this.config.maxRequests - validRequests.length);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Reset rate limit for identifier
|
|
109
|
+
*/
|
|
110
|
+
reset(identifier) {
|
|
111
|
+
this.store.delete(identifier);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Reset all rate limits
|
|
115
|
+
*/
|
|
116
|
+
resetAll() {
|
|
117
|
+
this.store.clear();
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Clean up expired records
|
|
121
|
+
*/
|
|
122
|
+
cleanup() {
|
|
123
|
+
const now = Date.now();
|
|
124
|
+
for (const [key, record] of this.store.entries()) {
|
|
125
|
+
// Remove expired blocked records
|
|
126
|
+
if (record.blocked && record.blockedUntil && now >= record.blockedUntil) {
|
|
127
|
+
this.store.delete(key);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
// Remove records with no valid requests
|
|
131
|
+
const validRequests = record.requests.filter((time) => now - time < this.config.windowMs);
|
|
132
|
+
if (validRequests.length === 0) {
|
|
133
|
+
this.store.delete(key);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
record.requests = validRequests;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=RateLimiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RateLimiter.js","sourceRoot":"","sources":["../../src/services/RateLimiter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAYtD;;GAEG;AACH,MAAM,OAAO,WAAW;IACL,MAAM,CAAkB;IACxB,KAAK,GAAiC,IAAI,GAAG,EAAE,CAAC;IACzD,YAAY,GAA0B,IAAI,CAAC;IAC3C,MAAM,CAAU,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;IAEzE,YAAY,MAAuB;QACjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,gBAAgB;QACd,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,OAAO,CAAC,kBAAkB;QAC5B,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;YACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC,EAAE,WAAW,CAAC,mBAAmB,CAAC,CAAC;QAEpC,mDAAmD;QACnD,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,eAAe;QACb,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,UAAkB;QAC3B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,uBAAuB;QACvB,IAAI,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAC1C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACrC,CAAC;QAED,mBAAmB;QACnB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI,MAAM,CAAC,YAAY,IAAI,GAAG,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC;gBACrD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;gBACjE,MAAM,IAAI,gBAAgB,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;YACtE,CAAC;YACD,cAAc;YACd,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;YACvB,MAAM,CAAC,YAAY,GAAG,SAAS,CAAC;QAClC,CAAC;QAED,qBAAqB;QACrB,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CACtC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAC5C,CAAC;QAEF,cAAc;QACd,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YACtD,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;YACtB,MAAM,CAAC,YAAY,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YACjD,MAAM,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE;gBACjE,OAAO,EAAE,EAAE,UAAU,EAAE;aACxB,CAAC,CAAC;QACL,CAAC;QAED,iBAAiB;QACjB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,UAAkB;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC;QAC1C,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,UAAkB;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QACjC,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAC1C,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAC5C,CAAC;QAEF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACrE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAkB;QACtB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,OAAO;QACL,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;YACjD,iCAAiC;YACjC,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,YAAY,IAAI,GAAG,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;gBACxE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACvB,SAAS;YACX,CAAC;YAED,wCAAwC;YACxC,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAC1C,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAC5C,CAAC;YACF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,QAAQ,GAAG,aAAa,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Service
|
|
3
|
+
* Provides input validation and sanitization
|
|
4
|
+
*/
|
|
5
|
+
import type { SanitizedCommand, ServerConfig, SSHConnectionConfig, ValidationResult } from "../types/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* Validation service for input sanitization and validation
|
|
8
|
+
*/
|
|
9
|
+
export declare class ValidationService {
|
|
10
|
+
private readonly allowedCommands;
|
|
11
|
+
private readonly blockedCommands;
|
|
12
|
+
constructor(options?: {
|
|
13
|
+
allowedCommands?: string[];
|
|
14
|
+
blockedCommands?: string[];
|
|
15
|
+
});
|
|
16
|
+
/**
|
|
17
|
+
* Validate and sanitize a command
|
|
18
|
+
*/
|
|
19
|
+
validateCommand(command: string): ValidationResult<SanitizedCommand>;
|
|
20
|
+
/**
|
|
21
|
+
* Validate server configuration
|
|
22
|
+
*/
|
|
23
|
+
validateServerConfig(data: Partial<ServerConfig>): ValidationResult<ServerConfig>;
|
|
24
|
+
/**
|
|
25
|
+
* Validate SSH connection configuration
|
|
26
|
+
*/
|
|
27
|
+
validateSSHConfig(config: SSHConnectionConfig): ValidationResult<SSHConnectionConfig>;
|
|
28
|
+
/**
|
|
29
|
+
* Validate a path for file operations
|
|
30
|
+
*/
|
|
31
|
+
validatePath(inputPath: string, basePath?: string): ValidationResult<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Validate a host address
|
|
34
|
+
*/
|
|
35
|
+
validateHost(host: string): ValidationResult<string>;
|
|
36
|
+
/**
|
|
37
|
+
* Validate a port number
|
|
38
|
+
*/
|
|
39
|
+
validatePort(port: number): ValidationResult<number>;
|
|
40
|
+
/**
|
|
41
|
+
* Parse and validate a port from string
|
|
42
|
+
*/
|
|
43
|
+
parsePort(portStr: string): ValidationResult<number>;
|
|
44
|
+
/**
|
|
45
|
+
* Sanitize a command string
|
|
46
|
+
*/
|
|
47
|
+
sanitizeCommand(command: string): SanitizedCommand;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=ValidationService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ValidationService.d.ts","sourceRoot":"","sources":["../../src/services/ValidationService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAS3B;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAuB;IACvD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAuB;gBAE3C,OAAO,CAAC,EAAE;QACpB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;KAC5B;IAKD;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAAC,gBAAgB,CAAC;IA+BpE;;OAEG;IACH,oBAAoB,CAClB,IAAI,EAAE,OAAO,CAAC,YAAY,CAAC,GAC1B,gBAAgB,CAAC,YAAY,CAAC;IAyDjC;;OAEG;IACH,iBAAiB,CACf,MAAM,EAAE,mBAAmB,GAC1B,gBAAgB,CAAC,mBAAmB,CAAC;IAgCxC;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAI5E;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAIpD;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAIpD;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IAIpD;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB;CAGnD"}
|