@serve.zone/dcrouter 11.14.0 → 11.16.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 (207) hide show
  1. package/dist_serve/bundle.js +5 -9
  2. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  3. package/dist_ts/00_commitinfo_data.js +9 -0
  4. package/dist_ts/cache/classes.cache.cleaner.d.ts +47 -0
  5. package/dist_ts/cache/classes.cache.cleaner.js +130 -0
  6. package/dist_ts/cache/classes.cached.document.d.ts +76 -0
  7. package/dist_ts/cache/classes.cached.document.js +100 -0
  8. package/dist_ts/cache/classes.cachedb.d.ts +60 -0
  9. package/dist_ts/cache/classes.cachedb.js +126 -0
  10. package/dist_ts/cache/documents/classes.cached.email.d.ts +125 -0
  11. package/dist_ts/cache/documents/classes.cached.email.js +337 -0
  12. package/dist_ts/cache/documents/classes.cached.ip.reputation.d.ts +119 -0
  13. package/dist_ts/cache/documents/classes.cached.ip.reputation.js +323 -0
  14. package/dist_ts/cache/documents/index.d.ts +2 -0
  15. package/dist_ts/cache/documents/index.js +3 -0
  16. package/dist_ts/cache/index.d.ts +4 -0
  17. package/dist_ts/cache/index.js +7 -0
  18. package/dist_ts/classes.cert-provision-scheduler.d.ts +54 -0
  19. package/dist_ts/classes.cert-provision-scheduler.js +118 -0
  20. package/dist_ts/classes.dcrouter.d.ts +399 -0
  21. package/dist_ts/classes.dcrouter.js +1697 -0
  22. package/dist_ts/classes.storage-cert-manager.d.ts +18 -0
  23. package/dist_ts/classes.storage-cert-manager.js +43 -0
  24. package/dist_ts/config/classes.api-token-manager.d.ts +46 -0
  25. package/dist_ts/config/classes.api-token-manager.js +150 -0
  26. package/dist_ts/config/classes.route-config-manager.d.ts +38 -0
  27. package/dist_ts/config/classes.route-config-manager.js +257 -0
  28. package/dist_ts/config/index.d.ts +3 -0
  29. package/dist_ts/config/index.js +5 -0
  30. package/dist_ts/config/validator.d.ts +104 -0
  31. package/dist_ts/config/validator.js +152 -0
  32. package/dist_ts/errors/base.errors.d.ts +224 -0
  33. package/dist_ts/errors/base.errors.js +320 -0
  34. package/dist_ts/errors/error-handler.d.ts +98 -0
  35. package/dist_ts/errors/error-handler.js +282 -0
  36. package/dist_ts/errors/error.codes.d.ts +115 -0
  37. package/dist_ts/errors/error.codes.js +136 -0
  38. package/dist_ts/errors/index.d.ts +54 -0
  39. package/dist_ts/errors/index.js +136 -0
  40. package/dist_ts/errors/reputation.errors.d.ts +183 -0
  41. package/dist_ts/errors/reputation.errors.js +292 -0
  42. package/dist_ts/http3/http3-route-augmentation.d.ts +50 -0
  43. package/dist_ts/http3/http3-route-augmentation.js +98 -0
  44. package/dist_ts/http3/index.d.ts +1 -0
  45. package/dist_ts/http3/index.js +2 -0
  46. package/dist_ts/index.d.ts +8 -0
  47. package/dist_ts/index.js +29 -0
  48. package/dist_ts/logger.d.ts +21 -0
  49. package/dist_ts/logger.js +81 -0
  50. package/dist_ts/monitoring/classes.metricscache.d.ts +32 -0
  51. package/dist_ts/monitoring/classes.metricscache.js +63 -0
  52. package/dist_ts/monitoring/classes.metricsmanager.d.ts +184 -0
  53. package/dist_ts/monitoring/classes.metricsmanager.js +744 -0
  54. package/dist_ts/monitoring/index.d.ts +1 -0
  55. package/dist_ts/monitoring/index.js +2 -0
  56. package/dist_ts/opsserver/classes.opsserver.d.ts +38 -0
  57. package/dist_ts/opsserver/classes.opsserver.js +87 -0
  58. package/dist_ts/opsserver/handlers/admin.handler.d.ts +31 -0
  59. package/dist_ts/opsserver/handlers/admin.handler.js +180 -0
  60. package/dist_ts/opsserver/handlers/api-token.handler.d.ts +6 -0
  61. package/dist_ts/opsserver/handlers/api-token.handler.js +62 -0
  62. package/dist_ts/opsserver/handlers/certificate.handler.d.ts +32 -0
  63. package/dist_ts/opsserver/handlers/certificate.handler.js +421 -0
  64. package/dist_ts/opsserver/handlers/config.handler.d.ts +7 -0
  65. package/dist_ts/opsserver/handlers/config.handler.js +192 -0
  66. package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +30 -0
  67. package/dist_ts/opsserver/handlers/email-ops.handler.js +227 -0
  68. package/dist_ts/opsserver/handlers/index.d.ts +12 -0
  69. package/dist_ts/opsserver/handlers/index.js +13 -0
  70. package/dist_ts/opsserver/handlers/logs.handler.d.ts +25 -0
  71. package/dist_ts/opsserver/handlers/logs.handler.js +256 -0
  72. package/dist_ts/opsserver/handlers/radius.handler.d.ts +6 -0
  73. package/dist_ts/opsserver/handlers/radius.handler.js +295 -0
  74. package/dist_ts/opsserver/handlers/remoteingress.handler.d.ts +6 -0
  75. package/dist_ts/opsserver/handlers/remoteingress.handler.js +156 -0
  76. package/dist_ts/opsserver/handlers/route-management.handler.d.ts +14 -0
  77. package/dist_ts/opsserver/handlers/route-management.handler.js +117 -0
  78. package/dist_ts/opsserver/handlers/security.handler.d.ts +9 -0
  79. package/dist_ts/opsserver/handlers/security.handler.js +233 -0
  80. package/dist_ts/opsserver/handlers/stats.handler.d.ts +11 -0
  81. package/dist_ts/opsserver/handlers/stats.handler.js +403 -0
  82. package/dist_ts/opsserver/handlers/vpn.handler.d.ts +6 -0
  83. package/dist_ts/opsserver/handlers/vpn.handler.js +197 -0
  84. package/dist_ts/opsserver/helpers/guards.d.ts +27 -0
  85. package/dist_ts/opsserver/helpers/guards.js +43 -0
  86. package/dist_ts/opsserver/index.d.ts +1 -0
  87. package/dist_ts/opsserver/index.js +2 -0
  88. package/dist_ts/paths.d.ts +26 -0
  89. package/dist_ts/paths.js +45 -0
  90. package/dist_ts/plugins.d.ts +81 -0
  91. package/dist_ts/plugins.js +115 -0
  92. package/dist_ts/radius/classes.accounting.manager.d.ts +231 -0
  93. package/dist_ts/radius/classes.accounting.manager.js +462 -0
  94. package/dist_ts/radius/classes.radius.server.d.ts +171 -0
  95. package/dist_ts/radius/classes.radius.server.js +386 -0
  96. package/dist_ts/radius/classes.vlan.manager.d.ts +128 -0
  97. package/dist_ts/radius/classes.vlan.manager.js +279 -0
  98. package/dist_ts/radius/index.d.ts +13 -0
  99. package/dist_ts/radius/index.js +14 -0
  100. package/dist_ts/remoteingress/classes.remoteingress-manager.d.ts +94 -0
  101. package/dist_ts/remoteingress/classes.remoteingress-manager.js +271 -0
  102. package/dist_ts/remoteingress/classes.tunnel-manager.d.ts +59 -0
  103. package/dist_ts/remoteingress/classes.tunnel-manager.js +165 -0
  104. package/dist_ts/remoteingress/index.d.ts +2 -0
  105. package/dist_ts/remoteingress/index.js +3 -0
  106. package/dist_ts/security/classes.contentscanner.d.ts +164 -0
  107. package/dist_ts/security/classes.contentscanner.js +642 -0
  108. package/dist_ts/security/classes.ipreputationchecker.d.ts +160 -0
  109. package/dist_ts/security/classes.ipreputationchecker.js +537 -0
  110. package/dist_ts/security/classes.securitylogger.d.ts +144 -0
  111. package/dist_ts/security/classes.securitylogger.js +235 -0
  112. package/dist_ts/security/index.d.ts +3 -0
  113. package/dist_ts/security/index.js +4 -0
  114. package/dist_ts/sms/classes.smsservice.d.ts +15 -0
  115. package/dist_ts/sms/classes.smsservice.js +72 -0
  116. package/dist_ts/sms/config/sms.config.d.ts +93 -0
  117. package/dist_ts/sms/config/sms.config.js +2 -0
  118. package/dist_ts/sms/config/sms.schema.d.ts +5 -0
  119. package/dist_ts/sms/config/sms.schema.js +121 -0
  120. package/dist_ts/sms/index.d.ts +1 -0
  121. package/dist_ts/sms/index.js +2 -0
  122. package/dist_ts/storage/classes.storagemanager.d.ts +83 -0
  123. package/dist_ts/storage/classes.storagemanager.js +348 -0
  124. package/dist_ts/storage/index.d.ts +1 -0
  125. package/dist_ts/storage/index.js +3 -0
  126. package/dist_ts/vpn/classes.vpn-manager.d.ts +129 -0
  127. package/dist_ts/vpn/classes.vpn-manager.js +329 -0
  128. package/dist_ts/vpn/index.d.ts +1 -0
  129. package/dist_ts/vpn/index.js +2 -0
  130. package/dist_ts_apiclient/classes.apitoken.d.ts +41 -0
  131. package/dist_ts_apiclient/classes.apitoken.js +115 -0
  132. package/dist_ts_apiclient/classes.certificate.d.ts +57 -0
  133. package/dist_ts_apiclient/classes.certificate.js +69 -0
  134. package/dist_ts_apiclient/classes.config.d.ts +7 -0
  135. package/dist_ts_apiclient/classes.config.js +11 -0
  136. package/dist_ts_apiclient/classes.dcrouterapiclient.d.ts +41 -0
  137. package/dist_ts_apiclient/classes.dcrouterapiclient.js +81 -0
  138. package/dist_ts_apiclient/classes.email.d.ts +30 -0
  139. package/dist_ts_apiclient/classes.email.js +52 -0
  140. package/dist_ts_apiclient/classes.logs.d.ts +21 -0
  141. package/dist_ts_apiclient/classes.logs.js +14 -0
  142. package/dist_ts_apiclient/classes.radius.d.ts +59 -0
  143. package/dist_ts_apiclient/classes.radius.js +95 -0
  144. package/dist_ts_apiclient/classes.remoteingress.d.ts +54 -0
  145. package/dist_ts_apiclient/classes.remoteingress.js +136 -0
  146. package/dist_ts_apiclient/classes.route.d.ts +42 -0
  147. package/dist_ts_apiclient/classes.route.js +154 -0
  148. package/dist_ts_apiclient/classes.stats.d.ts +47 -0
  149. package/dist_ts_apiclient/classes.stats.js +38 -0
  150. package/dist_ts_apiclient/index.d.ts +10 -0
  151. package/dist_ts_apiclient/index.js +14 -0
  152. package/dist_ts_apiclient/plugins.d.ts +3 -0
  153. package/dist_ts_apiclient/plugins.js +5 -0
  154. package/dist_ts_interfaces/data/remoteingress.d.ts +2 -0
  155. package/dist_ts_interfaces/data/vpn.d.ts +1 -2
  156. package/dist_ts_interfaces/requests/vpn.d.ts +1 -1
  157. package/dist_ts_web/00_commitinfo_data.d.ts +8 -0
  158. package/dist_ts_web/00_commitinfo_data.js +9 -0
  159. package/dist_ts_web/appstate.d.ts +238 -0
  160. package/dist_ts_web/appstate.js +1174 -0
  161. package/dist_ts_web/elements/index.d.ts +13 -0
  162. package/dist_ts_web/elements/index.js +14 -0
  163. package/dist_ts_web/elements/ops-dashboard.d.ts +23 -0
  164. package/dist_ts_web/elements/ops-dashboard.js +323 -0
  165. package/dist_ts_web/elements/ops-view-apitokens.d.ts +13 -0
  166. package/dist_ts_web/elements/ops-view-apitokens.js +371 -0
  167. package/dist_ts_web/elements/ops-view-certificates.d.ts +22 -0
  168. package/dist_ts_web/elements/ops-view-certificates.js +528 -0
  169. package/dist_ts_web/elements/ops-view-config.d.ts +19 -0
  170. package/dist_ts_web/elements/ops-view-config.js +339 -0
  171. package/dist_ts_web/elements/ops-view-emails.d.ts +21 -0
  172. package/dist_ts_web/elements/ops-view-emails.js +165 -0
  173. package/dist_ts_web/elements/ops-view-logs.d.ts +13 -0
  174. package/dist_ts_web/elements/ops-view-logs.js +159 -0
  175. package/dist_ts_web/elements/ops-view-network.d.ts +71 -0
  176. package/dist_ts_web/elements/ops-view-network.js +764 -0
  177. package/dist_ts_web/elements/ops-view-overview.d.ts +22 -0
  178. package/dist_ts_web/elements/ops-view-overview.js +456 -0
  179. package/dist_ts_web/elements/ops-view-remoteingress.d.ts +20 -0
  180. package/dist_ts_web/elements/ops-view-remoteingress.js +494 -0
  181. package/dist_ts_web/elements/ops-view-routes.d.ts +12 -0
  182. package/dist_ts_web/elements/ops-view-routes.js +404 -0
  183. package/dist_ts_web/elements/ops-view-security.d.ts +21 -0
  184. package/dist_ts_web/elements/ops-view-security.js +574 -0
  185. package/dist_ts_web/elements/ops-view-vpn.d.ts +14 -0
  186. package/dist_ts_web/elements/ops-view-vpn.js +365 -0
  187. package/dist_ts_web/elements/shared/css.d.ts +1 -0
  188. package/dist_ts_web/elements/shared/css.js +10 -0
  189. package/dist_ts_web/elements/shared/index.d.ts +2 -0
  190. package/dist_ts_web/elements/shared/index.js +3 -0
  191. package/dist_ts_web/elements/shared/ops-sectionheading.d.ts +5 -0
  192. package/dist_ts_web/elements/shared/ops-sectionheading.js +82 -0
  193. package/dist_ts_web/index.d.ts +1 -0
  194. package/dist_ts_web/index.js +10 -0
  195. package/dist_ts_web/plugins.d.ts +6 -0
  196. package/dist_ts_web/plugins.js +11 -0
  197. package/dist_ts_web/router.d.ts +19 -0
  198. package/dist_ts_web/router.js +91 -0
  199. package/package.json +2 -2
  200. package/ts/00_commitinfo_data.ts +1 -1
  201. package/ts/classes.dcrouter.ts +51 -20
  202. package/ts/config/classes.route-config-manager.ts +7 -6
  203. package/ts/opsserver/handlers/vpn.handler.ts +3 -5
  204. package/ts/vpn/classes.vpn-manager.ts +68 -19
  205. package/ts_web/00_commitinfo_data.ts +1 -1
  206. package/ts_web/appstate.ts +2 -2
  207. package/ts_web/elements/ops-view-vpn.ts +5 -9
@@ -0,0 +1,403 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import * as interfaces from '../../../dist_ts_interfaces/index.js';
3
+ import { MetricsManager } from '../../monitoring/index.js';
4
+ import { SecurityLogger } from '../../security/classes.securitylogger.js';
5
+ export class StatsHandler {
6
+ opsServerRef;
7
+ constructor(opsServerRef) {
8
+ this.opsServerRef = opsServerRef;
9
+ this.registerHandlers();
10
+ }
11
+ registerHandlers() {
12
+ // All stats endpoints register directly on viewRouter (valid identity required via middleware)
13
+ const router = this.opsServerRef.viewRouter;
14
+ // Server Statistics Handler
15
+ router.addTypedHandler(new plugins.typedrequest.TypedHandler('getServerStatistics', async (dataArg, toolsArg) => {
16
+ const stats = await this.collectServerStats();
17
+ return {
18
+ stats: {
19
+ uptime: stats.uptime,
20
+ startTime: Date.now() - (stats.uptime * 1000),
21
+ memoryUsage: stats.memoryUsage,
22
+ cpuUsage: stats.cpuUsage,
23
+ activeConnections: stats.activeConnections,
24
+ totalConnections: stats.totalConnections,
25
+ requestsPerSecond: stats.requestsPerSecond,
26
+ throughput: stats.throughput,
27
+ },
28
+ history: dataArg.includeHistory ? stats.history : undefined,
29
+ };
30
+ }));
31
+ // Email Statistics Handler
32
+ router.addTypedHandler(new plugins.typedrequest.TypedHandler('getEmailStatistics', async (dataArg, toolsArg) => {
33
+ const emailServer = this.opsServerRef.dcRouterRef.emailServer;
34
+ if (!emailServer) {
35
+ return {
36
+ stats: {
37
+ sent: 0,
38
+ received: 0,
39
+ bounced: 0,
40
+ queued: 0,
41
+ failed: 0,
42
+ averageDeliveryTime: 0,
43
+ deliveryRate: 0,
44
+ bounceRate: 0,
45
+ },
46
+ };
47
+ }
48
+ const stats = await this.collectEmailStats();
49
+ return {
50
+ stats: {
51
+ sent: stats.sentToday,
52
+ received: stats.receivedToday,
53
+ bounced: Math.floor(stats.sentToday * stats.bounceRate / 100),
54
+ queued: stats.queueSize,
55
+ failed: 0,
56
+ averageDeliveryTime: 0,
57
+ deliveryRate: stats.deliveryRate,
58
+ bounceRate: stats.bounceRate,
59
+ },
60
+ domainBreakdown: dataArg.includeDetails ? stats.domainBreakdown : undefined,
61
+ };
62
+ }));
63
+ // DNS Statistics Handler
64
+ router.addTypedHandler(new plugins.typedrequest.TypedHandler('getDnsStatistics', async (dataArg, toolsArg) => {
65
+ const dnsServer = this.opsServerRef.dcRouterRef.dnsServer;
66
+ if (!dnsServer) {
67
+ return {
68
+ stats: {
69
+ totalQueries: 0,
70
+ cacheHits: 0,
71
+ cacheMisses: 0,
72
+ cacheHitRate: 0,
73
+ activeDomains: 0,
74
+ averageResponseTime: 0,
75
+ queryTypes: {},
76
+ },
77
+ };
78
+ }
79
+ const stats = await this.collectDnsStats();
80
+ return {
81
+ stats: {
82
+ totalQueries: stats.totalQueries,
83
+ cacheHits: stats.cacheHits,
84
+ cacheMisses: stats.cacheMisses,
85
+ cacheHitRate: stats.cacheHitRate,
86
+ activeDomains: stats.topDomains.length,
87
+ averageResponseTime: 0,
88
+ queryTypes: stats.queryTypes,
89
+ },
90
+ domainBreakdown: dataArg.includeQueryTypes ? stats.domainBreakdown : undefined,
91
+ };
92
+ }));
93
+ // Queue Status Handler
94
+ router.addTypedHandler(new plugins.typedrequest.TypedHandler('getQueueStatus', async (dataArg, toolsArg) => {
95
+ const emailServer = this.opsServerRef.dcRouterRef.emailServer;
96
+ const queues = [];
97
+ if (emailServer) {
98
+ const status = await this.getQueueStatus();
99
+ queues.push({
100
+ name: dataArg.queueName || 'default',
101
+ size: status.pending,
102
+ processing: status.active,
103
+ failed: status.failed,
104
+ retrying: status.retrying,
105
+ averageProcessingTime: 0,
106
+ });
107
+ }
108
+ return {
109
+ queues,
110
+ totalItems: queues.reduce((sum, q) => sum + q.size + q.processing + q.failed + q.retrying, 0),
111
+ };
112
+ }));
113
+ // Health Status Handler
114
+ router.addTypedHandler(new plugins.typedrequest.TypedHandler('getHealthStatus', async (dataArg, toolsArg) => {
115
+ const health = await this.checkHealthStatus();
116
+ return {
117
+ health: {
118
+ healthy: health.healthy,
119
+ uptime: process.uptime(),
120
+ services: health.services.reduce((acc, service) => {
121
+ acc[service.name] = {
122
+ status: service.status,
123
+ message: service.message,
124
+ lastCheck: Date.now(),
125
+ };
126
+ return acc;
127
+ }, {}),
128
+ version: '2.12.0', // TODO: Get from package.json
129
+ },
130
+ };
131
+ }));
132
+ // Combined Metrics Handler - More efficient for frontend polling
133
+ router.addTypedHandler(new plugins.typedrequest.TypedHandler('getCombinedMetrics', async (dataArg, toolsArg) => {
134
+ const sections = dataArg.sections || {
135
+ server: true,
136
+ email: true,
137
+ dns: true,
138
+ security: true,
139
+ network: true,
140
+ };
141
+ const metrics = {};
142
+ // Run all metrics collection in parallel
143
+ const promises = [];
144
+ if (sections.server) {
145
+ promises.push(this.collectServerStats().then(stats => {
146
+ metrics.server = {
147
+ uptime: stats.uptime,
148
+ startTime: Date.now() - (stats.uptime * 1000),
149
+ memoryUsage: stats.memoryUsage,
150
+ cpuUsage: stats.cpuUsage,
151
+ activeConnections: stats.activeConnections,
152
+ totalConnections: stats.totalConnections,
153
+ requestsPerSecond: stats.requestsPerSecond,
154
+ throughput: stats.throughput,
155
+ };
156
+ }));
157
+ }
158
+ if (sections.email) {
159
+ promises.push(this.collectEmailStats().then(stats => {
160
+ // Get time-series data from MetricsManager
161
+ const timeSeries = this.opsServerRef.dcRouterRef.metricsManager
162
+ ? this.opsServerRef.dcRouterRef.metricsManager.getEmailTimeSeries(24)
163
+ : undefined;
164
+ metrics.email = {
165
+ sent: stats.sentToday,
166
+ received: stats.receivedToday,
167
+ bounced: Math.floor(stats.sentToday * stats.bounceRate / 100),
168
+ queued: stats.queueSize,
169
+ failed: 0,
170
+ averageDeliveryTime: 0,
171
+ deliveryRate: stats.deliveryRate,
172
+ bounceRate: stats.bounceRate,
173
+ timeSeries,
174
+ };
175
+ }));
176
+ }
177
+ if (sections.dns) {
178
+ promises.push(this.collectDnsStats().then(stats => {
179
+ // Get time-series data from MetricsManager
180
+ const timeSeries = this.opsServerRef.dcRouterRef.metricsManager
181
+ ? this.opsServerRef.dcRouterRef.metricsManager.getDnsTimeSeries(24)
182
+ : undefined;
183
+ metrics.dns = {
184
+ totalQueries: stats.totalQueries,
185
+ cacheHits: stats.cacheHits,
186
+ cacheMisses: stats.cacheMisses,
187
+ cacheHitRate: stats.cacheHitRate,
188
+ activeDomains: stats.topDomains.length,
189
+ averageResponseTime: 0,
190
+ queryTypes: stats.queryTypes,
191
+ timeSeries,
192
+ recentQueries: stats.recentQueries,
193
+ };
194
+ }));
195
+ }
196
+ if (sections.security && this.opsServerRef.dcRouterRef.metricsManager) {
197
+ promises.push(this.opsServerRef.dcRouterRef.metricsManager.getSecurityStats().then(stats => {
198
+ // Get recent events from the SecurityLogger singleton
199
+ const securityLogger = SecurityLogger.getInstance();
200
+ const recentEvents = securityLogger.getRecentEvents(50).map((evt) => ({
201
+ timestamp: evt.timestamp,
202
+ level: evt.level,
203
+ type: evt.type,
204
+ message: evt.message,
205
+ details: evt.details,
206
+ ipAddress: evt.ipAddress,
207
+ domain: evt.domain,
208
+ success: evt.success,
209
+ }));
210
+ metrics.security = {
211
+ blockedIPs: stats.blockedIPs,
212
+ reputationScores: {},
213
+ spamDetected: stats.spamDetected,
214
+ malwareDetected: stats.malwareDetected,
215
+ phishingDetected: stats.phishingDetected,
216
+ authenticationFailures: stats.authFailures,
217
+ suspiciousActivities: stats.totalThreatsBlocked,
218
+ recentEvents,
219
+ };
220
+ }));
221
+ }
222
+ if (sections.network && this.opsServerRef.dcRouterRef.metricsManager) {
223
+ promises.push((async () => {
224
+ const stats = await this.opsServerRef.dcRouterRef.metricsManager.getNetworkStats();
225
+ const serverStats = await this.collectServerStats();
226
+ // Build per-IP bandwidth lookup from throughputByIP
227
+ const ipBandwidth = new Map();
228
+ if (stats.throughputByIP) {
229
+ for (const [ip, tp] of stats.throughputByIP) {
230
+ ipBandwidth.set(ip, { in: tp.in, out: tp.out });
231
+ }
232
+ }
233
+ metrics.network = {
234
+ totalBandwidth: {
235
+ in: stats.throughputRate.bytesInPerSecond,
236
+ out: stats.throughputRate.bytesOutPerSecond,
237
+ },
238
+ totalBytes: {
239
+ in: stats.totalDataTransferred.bytesIn,
240
+ out: stats.totalDataTransferred.bytesOut,
241
+ },
242
+ activeConnections: serverStats.activeConnections,
243
+ connectionDetails: [],
244
+ topEndpoints: stats.topIPs.map(ip => ({
245
+ endpoint: ip.ip,
246
+ requests: ip.count,
247
+ bandwidth: ipBandwidth.get(ip.ip) || { in: 0, out: 0 },
248
+ })),
249
+ throughputHistory: stats.throughputHistory || [],
250
+ requestsPerSecond: stats.requestsPerSecond || 0,
251
+ requestsTotal: stats.requestsTotal || 0,
252
+ backends: stats.backends || [],
253
+ };
254
+ })());
255
+ }
256
+ await Promise.all(promises);
257
+ return {
258
+ metrics,
259
+ timestamp: Date.now(),
260
+ };
261
+ }));
262
+ }
263
+ async collectServerStats() {
264
+ // Get metrics from MetricsManager if available
265
+ if (this.opsServerRef.dcRouterRef.metricsManager) {
266
+ const serverStats = await this.opsServerRef.dcRouterRef.metricsManager.getServerStats();
267
+ return {
268
+ uptime: serverStats.uptime,
269
+ cpuUsage: serverStats.cpuUsage,
270
+ memoryUsage: serverStats.memoryUsage,
271
+ requestsPerSecond: serverStats.requestsPerSecond,
272
+ activeConnections: serverStats.activeConnections,
273
+ totalConnections: serverStats.totalConnections,
274
+ throughput: serverStats.throughput,
275
+ history: [], // TODO: Implement history tracking
276
+ };
277
+ }
278
+ // Fallback to basic stats if MetricsManager not available
279
+ const uptime = process.uptime();
280
+ const memUsage = process.memoryUsage();
281
+ const cpuUsage = plugins.os.loadavg()[0] * 100 / plugins.os.cpus().length;
282
+ return {
283
+ uptime,
284
+ cpuUsage: {
285
+ user: cpuUsage * 0.7,
286
+ system: cpuUsage * 0.3,
287
+ },
288
+ memoryUsage: {
289
+ heapUsed: memUsage.heapUsed,
290
+ heapTotal: memUsage.heapTotal,
291
+ external: memUsage.external,
292
+ rss: memUsage.rss,
293
+ },
294
+ requestsPerSecond: 0,
295
+ activeConnections: 0,
296
+ totalConnections: 0,
297
+ throughput: { bytesIn: 0, bytesOut: 0, bytesInPerSecond: 0, bytesOutPerSecond: 0 },
298
+ history: [],
299
+ };
300
+ }
301
+ async collectEmailStats() {
302
+ // Get metrics from MetricsManager if available
303
+ if (this.opsServerRef.dcRouterRef.metricsManager) {
304
+ const emailStats = await this.opsServerRef.dcRouterRef.metricsManager.getEmailStats();
305
+ return {
306
+ sentToday: emailStats.sentToday,
307
+ receivedToday: emailStats.receivedToday,
308
+ bounceRate: emailStats.bounceRate,
309
+ deliveryRate: emailStats.deliveryRate,
310
+ queueSize: emailStats.queueSize,
311
+ };
312
+ }
313
+ // Fallback if MetricsManager not available
314
+ return {
315
+ sentToday: 0,
316
+ receivedToday: 0,
317
+ bounceRate: 0,
318
+ deliveryRate: 100,
319
+ queueSize: 0,
320
+ };
321
+ }
322
+ async collectDnsStats() {
323
+ // Get metrics from MetricsManager if available
324
+ if (this.opsServerRef.dcRouterRef.metricsManager) {
325
+ const dnsStats = await this.opsServerRef.dcRouterRef.metricsManager.getDnsStats();
326
+ return {
327
+ queriesPerSecond: dnsStats.queriesPerSecond,
328
+ totalQueries: dnsStats.totalQueries,
329
+ cacheHits: dnsStats.cacheHits,
330
+ cacheMisses: dnsStats.cacheMisses,
331
+ cacheHitRate: dnsStats.cacheHitRate,
332
+ topDomains: dnsStats.topDomains,
333
+ queryTypes: dnsStats.queryTypes,
334
+ recentQueries: dnsStats.recentQueries,
335
+ };
336
+ }
337
+ // Fallback if MetricsManager not available
338
+ return {
339
+ queriesPerSecond: 0,
340
+ totalQueries: 0,
341
+ cacheHits: 0,
342
+ cacheMisses: 0,
343
+ cacheHitRate: 0,
344
+ topDomains: [],
345
+ queryTypes: {},
346
+ };
347
+ }
348
+ async getQueueStatus() {
349
+ // TODO: Implement actual queue status collection
350
+ return {
351
+ pending: 0,
352
+ active: 0,
353
+ failed: 0,
354
+ retrying: 0,
355
+ items: [],
356
+ };
357
+ }
358
+ async checkHealthStatus() {
359
+ const dcRouter = this.opsServerRef.dcRouterRef;
360
+ const health = dcRouter.serviceManager.getHealth();
361
+ const services = health.services.map((svc) => {
362
+ let status;
363
+ switch (svc.state) {
364
+ case 'running':
365
+ status = 'healthy';
366
+ break;
367
+ case 'starting':
368
+ case 'degraded':
369
+ status = 'degraded';
370
+ break;
371
+ case 'failed':
372
+ status = svc.criticality === 'critical' ? 'unhealthy' : 'degraded';
373
+ break;
374
+ case 'stopped':
375
+ case 'stopping':
376
+ default:
377
+ status = 'degraded';
378
+ break;
379
+ }
380
+ let message;
381
+ if (svc.state === 'failed' && svc.lastError) {
382
+ message = svc.lastError;
383
+ }
384
+ else if (svc.retryCount > 0 && svc.state !== 'running') {
385
+ message = `Retry attempt ${svc.retryCount}`;
386
+ }
387
+ return { name: svc.name, status, message };
388
+ });
389
+ const healthy = health.overall === 'healthy';
390
+ return {
391
+ healthy,
392
+ services,
393
+ checks: [
394
+ {
395
+ name: 'Memory Usage',
396
+ passed: process.memoryUsage().heapUsed < (plugins.os.totalmem() * 0.9),
397
+ message: 'Memory usage within limits',
398
+ },
399
+ ],
400
+ };
401
+ }
402
+ }
403
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdHMuaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL29wc3NlcnZlci9oYW5kbGVycy9zdGF0cy5oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFFNUMsT0FBTyxLQUFLLFVBQVUsTUFBTSxpQ0FBaUMsQ0FBQztBQUM5RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDBDQUEwQyxDQUFDO0FBRTFFLE1BQU0sT0FBTyxZQUFZO0lBQ0g7SUFBcEIsWUFBb0IsWUFBdUI7UUFBdkIsaUJBQVksR0FBWixZQUFZLENBQVc7UUFDekMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVPLGdCQUFnQjtRQUN0QiwrRkFBK0Y7UUFDL0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUM7UUFFNUMsNEJBQTRCO1FBQzVCLE1BQU0sQ0FBQyxlQUFlLENBQ3BCLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQ25DLHFCQUFxQixFQUNyQixLQUFLLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUFFO1lBQzFCLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDOUMsT0FBTztnQkFDTCxLQUFLLEVBQUU7b0JBQ0wsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO29CQUNwQixTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7b0JBQzdDLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVztvQkFDOUIsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRO29CQUN4QixpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO29CQUMxQyxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsZ0JBQWdCO29CQUN4QyxpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO29CQUMxQyxVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVU7aUJBQzdCO2dCQUNELE9BQU8sRUFBRSxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTO2FBQzVELENBQUM7UUFDSixDQUFDLENBQ0YsQ0FDRixDQUFDO1FBRUYsMkJBQTJCO1FBQzNCLE1BQU0sQ0FBQyxlQUFlLENBQ3BCLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQ25DLG9CQUFvQixFQUNwQixLQUFLLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUFFO1lBQzFCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQztZQUM5RCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ2pCLE9BQU87b0JBQ0wsS0FBSyxFQUFFO3dCQUNMLElBQUksRUFBRSxDQUFDO3dCQUNQLFFBQVEsRUFBRSxDQUFDO3dCQUNYLE9BQU8sRUFBRSxDQUFDO3dCQUNWLE1BQU0sRUFBRSxDQUFDO3dCQUNULE1BQU0sRUFBRSxDQUFDO3dCQUNULG1CQUFtQixFQUFFLENBQUM7d0JBQ3RCLFlBQVksRUFBRSxDQUFDO3dCQUNmLFVBQVUsRUFBRSxDQUFDO3FCQUNkO2lCQUNGLENBQUM7WUFDSixDQUFDO1lBRUQsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUM3QyxPQUFPO2dCQUNMLEtBQUssRUFBRTtvQkFDTCxJQUFJLEVBQUUsS0FBSyxDQUFDLFNBQVM7b0JBQ3JCLFFBQVEsRUFBRSxLQUFLLENBQUMsYUFBYTtvQkFDN0IsT0FBTyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQztvQkFDN0QsTUFBTSxFQUFFLEtBQUssQ0FBQyxTQUFTO29CQUN2QixNQUFNLEVBQUUsQ0FBQztvQkFDVCxtQkFBbUIsRUFBRSxDQUFDO29CQUN0QixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVk7b0JBQ2hDLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVTtpQkFDN0I7Z0JBQ0QsZUFBZSxFQUFFLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLFNBQVM7YUFDNUUsQ0FBQztRQUNKLENBQUMsQ0FDRixDQUNGLENBQUM7UUFFRix5QkFBeUI7UUFDekIsTUFBTSxDQUFDLGVBQWUsQ0FDcEIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDbkMsa0JBQWtCLEVBQ2xCLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEVBQUU7WUFDMUIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDO1lBQzFELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDZixPQUFPO29CQUNMLEtBQUssRUFBRTt3QkFDTCxZQUFZLEVBQUUsQ0FBQzt3QkFDZixTQUFTLEVBQUUsQ0FBQzt3QkFDWixXQUFXLEVBQUUsQ0FBQzt3QkFDZCxZQUFZLEVBQUUsQ0FBQzt3QkFDZixhQUFhLEVBQUUsQ0FBQzt3QkFDaEIsbUJBQW1CLEVBQUUsQ0FBQzt3QkFDdEIsVUFBVSxFQUFFLEVBQUU7cUJBQ2Y7aUJBQ0YsQ0FBQztZQUNKLENBQUM7WUFFRCxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUMzQyxPQUFPO2dCQUNMLEtBQUssRUFBRTtvQkFDTCxZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVk7b0JBQ2hDLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUztvQkFDMUIsV0FBVyxFQUFFLEtBQUssQ0FBQyxXQUFXO29CQUM5QixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVk7b0JBQ2hDLGFBQWEsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLE1BQU07b0JBQ3RDLG1CQUFtQixFQUFFLENBQUM7b0JBQ3RCLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVTtpQkFDN0I7Z0JBQ0QsZUFBZSxFQUFFLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsU0FBUzthQUMvRSxDQUFDO1FBQ0osQ0FBQyxDQUNGLENBQ0YsQ0FBQztRQUVGLHVCQUF1QjtRQUN2QixNQUFNLENBQUMsZUFBZSxDQUNwQixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUNuQyxnQkFBZ0IsRUFDaEIsS0FBSyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsRUFBRTtZQUMxQixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUM7WUFDOUQsTUFBTSxNQUFNLEdBQW1DLEVBQUUsQ0FBQztZQUVsRCxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNoQixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDM0MsTUFBTSxDQUFDLElBQUksQ0FBQztvQkFDVixJQUFJLEVBQUUsT0FBTyxDQUFDLFNBQVMsSUFBSSxTQUFTO29CQUNwQyxJQUFJLEVBQUUsTUFBTSxDQUFDLE9BQU87b0JBQ3BCLFVBQVUsRUFBRSxNQUFNLENBQUMsTUFBTTtvQkFDekIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO29CQUNyQixRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVE7b0JBQ3pCLHFCQUFxQixFQUFFLENBQUM7aUJBQ3pCLENBQUMsQ0FBQztZQUNMLENBQUM7WUFFRCxPQUFPO2dCQUNMLE1BQU07Z0JBQ04sVUFBVSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7YUFDOUYsQ0FBQztRQUNKLENBQUMsQ0FDRixDQUNGLENBQUM7UUFFRix3QkFBd0I7UUFDeEIsTUFBTSxDQUFDLGVBQWUsQ0FDcEIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDbkMsaUJBQWlCLEVBQ2pCLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEVBQUU7WUFDMUIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUM5QyxPQUFPO2dCQUNMLE1BQU0sRUFBRTtvQkFDTixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU87b0JBQ3ZCLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTSxFQUFFO29CQUN4QixRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxFQUFFLEVBQUU7d0JBQ2hELEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUc7NEJBQ2xCLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTs0QkFDdEIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPOzRCQUN4QixTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTt5QkFDdEIsQ0FBQzt3QkFDRixPQUFPLEdBQUcsQ0FBQztvQkFDYixDQUFDLEVBQUUsRUFBUyxDQUFDO29CQUNiLE9BQU8sRUFBRSxRQUFRLEVBQUUsOEJBQThCO2lCQUNsRDthQUNGLENBQUM7UUFDSixDQUFDLENBQ0YsQ0FDRixDQUFDO1FBRUYsaUVBQWlFO1FBQ2pFLE1BQU0sQ0FBQyxlQUFlLENBQ3BCLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQ25DLG9CQUFvQixFQUNwQixLQUFLLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUFFO1lBQzFCLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLElBQUk7Z0JBQ25DLE1BQU0sRUFBRSxJQUFJO2dCQUNaLEtBQUssRUFBRSxJQUFJO2dCQUNYLEdBQUcsRUFBRSxJQUFJO2dCQUNULFFBQVEsRUFBRSxJQUFJO2dCQUNkLE9BQU8sRUFBRSxJQUFJO2FBQ2QsQ0FBQztZQUVGLE1BQU0sT0FBTyxHQUFRLEVBQUUsQ0FBQztZQUV4Qix5Q0FBeUM7WUFDekMsTUFBTSxRQUFRLEdBQW9CLEVBQUUsQ0FBQztZQUVyQyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDcEIsUUFBUSxDQUFDLElBQUksQ0FDWCxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQ3JDLE9BQU8sQ0FBQyxNQUFNLEdBQUc7d0JBQ2YsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO3dCQUNwQixTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7d0JBQzdDLFdBQVcsRUFBRSxLQUFLLENBQUMsV0FBVzt3QkFDOUIsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRO3dCQUN4QixpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO3dCQUMxQyxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsZ0JBQWdCO3dCQUN4QyxpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO3dCQUMxQyxVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVU7cUJBQzdCLENBQUM7Z0JBQ0osQ0FBQyxDQUFDLENBQ0gsQ0FBQztZQUNKLENBQUM7WUFFRCxJQUFJLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDbkIsUUFBUSxDQUFDLElBQUksQ0FDWCxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQ3BDLDJDQUEyQztvQkFDM0MsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYzt3QkFDN0QsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7d0JBQ3JFLENBQUMsQ0FBQyxTQUFTLENBQUM7b0JBRWQsT0FBTyxDQUFDLEtBQUssR0FBRzt3QkFDZCxJQUFJLEVBQUUsS0FBSyxDQUFDLFNBQVM7d0JBQ3JCLFFBQVEsRUFBRSxLQUFLLENBQUMsYUFBYTt3QkFDN0IsT0FBTyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQzt3QkFDN0QsTUFBTSxFQUFFLEtBQUssQ0FBQyxTQUFTO3dCQUN2QixNQUFNLEVBQUUsQ0FBQzt3QkFDVCxtQkFBbUIsRUFBRSxDQUFDO3dCQUN0QixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVk7d0JBQ2hDLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVTt3QkFDNUIsVUFBVTtxQkFDWCxDQUFDO2dCQUNKLENBQUMsQ0FBQyxDQUNILENBQUM7WUFDSixDQUFDO1lBRUQsSUFBSSxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQ2pCLFFBQVEsQ0FBQyxJQUFJLENBQ1gsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRTtvQkFDbEMsMkNBQTJDO29CQUMzQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxjQUFjO3dCQUM3RCxDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsQ0FBQzt3QkFDbkUsQ0FBQyxDQUFDLFNBQVMsQ0FBQztvQkFFZCxPQUFPLENBQUMsR0FBRyxHQUFHO3dCQUNaLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWTt3QkFDaEMsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO3dCQUMxQixXQUFXLEVBQUUsS0FBSyxDQUFDLFdBQVc7d0JBQzlCLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWTt3QkFDaEMsYUFBYSxFQUFFLEtBQUssQ0FBQyxVQUFVLENBQUMsTUFBTTt3QkFDdEMsbUJBQW1CLEVBQUUsQ0FBQzt3QkFDdEIsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVO3dCQUM1QixVQUFVO3dCQUNWLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYTtxQkFDbkMsQ0FBQztnQkFDSixDQUFDLENBQUMsQ0FDSCxDQUFDO1lBQ0osQ0FBQztZQUVELElBQUksUUFBUSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDdEUsUUFBUSxDQUFDLElBQUksQ0FDWCxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQzNFLHNEQUFzRDtvQkFDdEQsTUFBTSxjQUFjLEdBQUcsY0FBYyxDQUFDLFdBQVcsRUFBRSxDQUFDO29CQUNwRCxNQUFNLFlBQVksR0FBRyxjQUFjLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQzt3QkFDcEUsU0FBUyxFQUFFLEdBQUcsQ0FBQyxTQUFTO3dCQUN4QixLQUFLLEVBQUUsR0FBRyxDQUFDLEtBQUs7d0JBQ2hCLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSTt3QkFDZCxPQUFPLEVBQUUsR0FBRyxDQUFDLE9BQU87d0JBQ3BCLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTzt3QkFDcEIsU0FBUyxFQUFFLEdBQUcsQ0FBQyxTQUFTO3dCQUN4QixNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU07d0JBQ2xCLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTztxQkFDckIsQ0FBQyxDQUFDLENBQUM7b0JBRUosT0FBTyxDQUFDLFFBQVEsR0FBRzt3QkFDakIsVUFBVSxFQUFFLEtBQUssQ0FBQyxVQUFVO3dCQUM1QixnQkFBZ0IsRUFBRSxFQUFFO3dCQUNwQixZQUFZLEVBQUUsS0FBSyxDQUFDLFlBQVk7d0JBQ2hDLGVBQWUsRUFBRSxLQUFLLENBQUMsZUFBZTt3QkFDdEMsZ0JBQWdCLEVBQUUsS0FBSyxDQUFDLGdCQUFnQjt3QkFDeEMsc0JBQXNCLEVBQUUsS0FBSyxDQUFDLFlBQVk7d0JBQzFDLG9CQUFvQixFQUFFLEtBQUssQ0FBQyxtQkFBbUI7d0JBQy9DLFlBQVk7cUJBQ2IsQ0FBQztnQkFDSixDQUFDLENBQUMsQ0FDSCxDQUFDO1lBQ0osQ0FBQztZQUVELElBQUksUUFBUSxDQUFDLE9BQU8sSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxjQUFjLEVBQUUsQ0FBQztnQkFDckUsUUFBUSxDQUFDLElBQUksQ0FDWCxDQUFDLEtBQUssSUFBSSxFQUFFO29CQUNWLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBZSxDQUFDLGVBQWUsRUFBRSxDQUFDO29CQUNwRixNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO29CQUVwRCxvREFBb0Q7b0JBQ3BELE1BQU0sV0FBVyxHQUFHLElBQUksR0FBRyxFQUF1QyxDQUFDO29CQUNuRSxJQUFJLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQzt3QkFDekIsS0FBSyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxJQUFJLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQzs0QkFDNUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7d0JBQ2xELENBQUM7b0JBQ0gsQ0FBQztvQkFFRCxPQUFPLENBQUMsT0FBTyxHQUFHO3dCQUNoQixjQUFjLEVBQUU7NEJBQ2QsRUFBRSxFQUFFLEtBQUssQ0FBQyxjQUFjLENBQUMsZ0JBQWdCOzRCQUN6QyxHQUFHLEVBQUUsS0FBSyxDQUFDLGNBQWMsQ0FBQyxpQkFBaUI7eUJBQzVDO3dCQUNELFVBQVUsRUFBRTs0QkFDVixFQUFFLEVBQUUsS0FBSyxDQUFDLG9CQUFvQixDQUFDLE9BQU87NEJBQ3RDLEdBQUcsRUFBRSxLQUFLLENBQUMsb0JBQW9CLENBQUMsUUFBUTt5QkFDekM7d0JBQ0QsaUJBQWlCLEVBQUUsV0FBVyxDQUFDLGlCQUFpQjt3QkFDaEQsaUJBQWlCLEVBQUUsRUFBRTt3QkFDckIsWUFBWSxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQzs0QkFDcEMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxFQUFFOzRCQUNmLFFBQVEsRUFBRSxFQUFFLENBQUMsS0FBSzs0QkFDbEIsU0FBUyxFQUFFLFdBQVcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFO3lCQUN2RCxDQUFDLENBQUM7d0JBQ0gsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQixJQUFJLEVBQUU7d0JBQ2hELGlCQUFpQixFQUFFLEtBQUssQ0FBQyxpQkFBaUIsSUFBSSxDQUFDO3dCQUMvQyxhQUFhLEVBQUUsS0FBSyxDQUFDLGFBQWEsSUFBSSxDQUFDO3dCQUN2QyxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVEsSUFBSSxFQUFFO3FCQUMvQixDQUFDO2dCQUNKLENBQUMsQ0FBQyxFQUFFLENBQ0wsQ0FBQztZQUNKLENBQUM7WUFFRCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7WUFFNUIsT0FBTztnQkFDTCxPQUFPO2dCQUNQLFNBQVMsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO2FBQ3RCLENBQUM7UUFDSixDQUFDLENBQ0YsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVPLEtBQUssQ0FBQyxrQkFBa0I7UUFnQjlCLCtDQUErQztRQUMvQyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ2pELE1BQU0sV0FBVyxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3hGLE9BQU87Z0JBQ0wsTUFBTSxFQUFFLFdBQVcsQ0FBQyxNQUFNO2dCQUMxQixRQUFRLEVBQUUsV0FBVyxDQUFDLFFBQVE7Z0JBQzlCLFdBQVcsRUFBRSxXQUFXLENBQUMsV0FBVztnQkFDcEMsaUJBQWlCLEVBQUUsV0FBVyxDQUFDLGlCQUFpQjtnQkFDaEQsaUJBQWlCLEVBQUUsV0FBVyxDQUFDLGlCQUFpQjtnQkFDaEQsZ0JBQWdCLEVBQUUsV0FBVyxDQUFDLGdCQUFnQjtnQkFDOUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxVQUFVO2dCQUNsQyxPQUFPLEVBQUUsRUFBRSxFQUFFLG1DQUFtQzthQUNqRCxDQUFDO1FBQ0osQ0FBQztRQUVELDBEQUEwRDtRQUMxRCxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDaEMsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxHQUFHLE9BQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUMsTUFBTSxDQUFDO1FBRTFFLE9BQU87WUFDTCxNQUFNO1lBQ04sUUFBUSxFQUFFO2dCQUNSLElBQUksRUFBRSxRQUFRLEdBQUcsR0FBRztnQkFDcEIsTUFBTSxFQUFFLFFBQVEsR0FBRyxHQUFHO2FBQ3ZCO1lBQ0QsV0FBVyxFQUFFO2dCQUNYLFFBQVEsRUFBRSxRQUFRLENBQUMsUUFBUTtnQkFDM0IsU0FBUyxFQUFFLFFBQVEsQ0FBQyxTQUFTO2dCQUM3QixRQUFRLEVBQUUsUUFBUSxDQUFDLFFBQVE7Z0JBQzNCLEdBQUcsRUFBRSxRQUFRLENBQUMsR0FBRzthQUNsQjtZQUNELGlCQUFpQixFQUFFLENBQUM7WUFDcEIsaUJBQWlCLEVBQUUsQ0FBQztZQUNwQixnQkFBZ0IsRUFBRSxDQUFDO1lBQ25CLFVBQVUsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQyxFQUFFO1lBQ2xGLE9BQU8sRUFBRSxFQUFFO1NBQ1osQ0FBQztJQUNKLENBQUM7SUFFTyxLQUFLLENBQUMsaUJBQWlCO1FBUTdCLCtDQUErQztRQUMvQyxJQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ2pELE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3RGLE9BQU87Z0JBQ0wsU0FBUyxFQUFFLFVBQVUsQ0FBQyxTQUFTO2dCQUMvQixhQUFhLEVBQUUsVUFBVSxDQUFDLGFBQWE7Z0JBQ3ZDLFVBQVUsRUFBRSxVQUFVLENBQUMsVUFBVTtnQkFDakMsWUFBWSxFQUFFLFVBQVUsQ0FBQyxZQUFZO2dCQUNyQyxTQUFTLEVBQUUsVUFBVSxDQUFDLFNBQVM7YUFDaEMsQ0FBQztRQUNKLENBQUM7UUFFRCwyQ0FBMkM7UUFDM0MsT0FBTztZQUNMLFNBQVMsRUFBRSxDQUFDO1lBQ1osYUFBYSxFQUFFLENBQUM7WUFDaEIsVUFBVSxFQUFFLENBQUM7WUFDYixZQUFZLEVBQUUsR0FBRztZQUNqQixTQUFTLEVBQUUsQ0FBQztTQUNiLENBQUM7SUFDSixDQUFDO0lBRU8sS0FBSyxDQUFDLGVBQWU7UUFjM0IsK0NBQStDO1FBQy9DLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDakQsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbEYsT0FBTztnQkFDTCxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsZ0JBQWdCO2dCQUMzQyxZQUFZLEVBQUUsUUFBUSxDQUFDLFlBQVk7Z0JBQ25DLFNBQVMsRUFBRSxRQUFRLENBQUMsU0FBUztnQkFDN0IsV0FBVyxFQUFFLFFBQVEsQ0FBQyxXQUFXO2dCQUNqQyxZQUFZLEVBQUUsUUFBUSxDQUFDLFlBQVk7Z0JBQ25DLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVTtnQkFDL0IsVUFBVSxFQUFFLFFBQVEsQ0FBQyxVQUFVO2dCQUMvQixhQUFhLEVBQUUsUUFBUSxDQUFDLGFBQWE7YUFDdEMsQ0FBQztRQUNKLENBQUM7UUFFRCwyQ0FBMkM7UUFDM0MsT0FBTztZQUNMLGdCQUFnQixFQUFFLENBQUM7WUFDbkIsWUFBWSxFQUFFLENBQUM7WUFDZixTQUFTLEVBQUUsQ0FBQztZQUNaLFdBQVcsRUFBRSxDQUFDO1lBQ2QsWUFBWSxFQUFFLENBQUM7WUFDZixVQUFVLEVBQUUsRUFBRTtZQUNkLFVBQVUsRUFBRSxFQUFFO1NBQ2YsQ0FBQztJQUNKLENBQUM7SUFFTyxLQUFLLENBQUMsY0FBYztRQWMxQixpREFBaUQ7UUFDakQsT0FBTztZQUNMLE9BQU8sRUFBRSxDQUFDO1lBQ1YsTUFBTSxFQUFFLENBQUM7WUFDVCxNQUFNLEVBQUUsQ0FBQztZQUNULFFBQVEsRUFBRSxDQUFDO1lBQ1gsS0FBSyxFQUFFLEVBQUU7U0FDVixDQUFDO0lBQ0osQ0FBQztJQUVPLEtBQUssQ0FBQyxpQkFBaUI7UUFhN0IsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUM7UUFDL0MsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUVuRCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO1lBQzNDLElBQUksTUFBNEMsQ0FBQztZQUNqRCxRQUFRLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDbEIsS0FBSyxTQUFTO29CQUNaLE1BQU0sR0FBRyxTQUFTLENBQUM7b0JBQ25CLE1BQU07Z0JBQ1IsS0FBSyxVQUFVLENBQUM7Z0JBQ2hCLEtBQUssVUFBVTtvQkFDYixNQUFNLEdBQUcsVUFBVSxDQUFDO29CQUNwQixNQUFNO2dCQUNSLEtBQUssUUFBUTtvQkFDWCxNQUFNLEdBQUcsR0FBRyxDQUFDLFdBQVcsS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO29CQUNuRSxNQUFNO2dCQUNSLEtBQUssU0FBUyxDQUFDO2dCQUNmLEtBQUssVUFBVSxDQUFDO2dCQUNoQjtvQkFDRSxNQUFNLEdBQUcsVUFBVSxDQUFDO29CQUNwQixNQUFNO1lBQ1YsQ0FBQztZQUVELElBQUksT0FBMkIsQ0FBQztZQUNoQyxJQUFJLEdBQUcsQ0FBQyxLQUFLLEtBQUssUUFBUSxJQUFJLEdBQUcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDNUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxTQUFTLENBQUM7WUFDMUIsQ0FBQztpQkFBTSxJQUFJLEdBQUcsQ0FBQyxVQUFVLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxLQUFLLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ3pELE9BQU8sR0FBRyxpQkFBaUIsR0FBRyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzlDLENBQUM7WUFFRCxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxDQUFDO1FBQzdDLENBQUMsQ0FBQyxDQUFDO1FBRUgsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sS0FBSyxTQUFTLENBQUM7UUFFN0MsT0FBTztZQUNMLE9BQU87WUFDUCxRQUFRO1lBQ1IsTUFBTSxFQUFFO2dCQUNOO29CQUNFLElBQUksRUFBRSxjQUFjO29CQUNwQixNQUFNLEVBQUUsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsUUFBUSxFQUFFLEdBQUcsR0FBRyxDQUFDO29CQUN0RSxPQUFPLEVBQUUsNEJBQTRCO2lCQUN0QzthQUNGO1NBQ0YsQ0FBQztJQUNKLENBQUM7Q0FDRiJ9
@@ -0,0 +1,6 @@
1
+ import type { OpsServer } from '../classes.opsserver.js';
2
+ export declare class VpnHandler {
3
+ private opsServerRef;
4
+ constructor(opsServerRef: OpsServer);
5
+ private registerHandlers;
6
+ }
@@ -0,0 +1,197 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import * as interfaces from '../../../dist_ts_interfaces/index.js';
3
+ export class VpnHandler {
4
+ opsServerRef;
5
+ constructor(opsServerRef) {
6
+ this.opsServerRef = opsServerRef;
7
+ this.registerHandlers();
8
+ }
9
+ registerHandlers() {
10
+ const viewRouter = this.opsServerRef.viewRouter;
11
+ const adminRouter = this.opsServerRef.adminRouter;
12
+ // ---- Read endpoints (viewRouter — valid identity required via middleware) ----
13
+ // Get all registered VPN clients
14
+ viewRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getVpnClients', async (dataArg, toolsArg) => {
15
+ const manager = this.opsServerRef.dcRouterRef.vpnManager;
16
+ if (!manager) {
17
+ return { clients: [] };
18
+ }
19
+ const clients = manager.listClients().map((c) => ({
20
+ clientId: c.clientId,
21
+ enabled: c.enabled,
22
+ serverDefinedClientTags: c.serverDefinedClientTags,
23
+ description: c.description,
24
+ assignedIp: c.assignedIp,
25
+ createdAt: c.createdAt,
26
+ updatedAt: c.updatedAt,
27
+ expiresAt: c.expiresAt,
28
+ }));
29
+ return { clients };
30
+ }));
31
+ // Get VPN server status
32
+ viewRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getVpnStatus', async (dataArg, toolsArg) => {
33
+ const manager = this.opsServerRef.dcRouterRef.vpnManager;
34
+ const vpnConfig = this.opsServerRef.dcRouterRef.options.vpnConfig;
35
+ if (!manager) {
36
+ return {
37
+ status: {
38
+ running: false,
39
+ subnet: vpnConfig?.subnet || '10.8.0.0/24',
40
+ wgListenPort: vpnConfig?.wgListenPort ?? 51820,
41
+ serverPublicKeys: null,
42
+ registeredClients: 0,
43
+ connectedClients: 0,
44
+ },
45
+ };
46
+ }
47
+ const connected = await manager.getConnectedClients();
48
+ return {
49
+ status: {
50
+ running: manager.running,
51
+ subnet: manager.getSubnet(),
52
+ wgListenPort: vpnConfig?.wgListenPort ?? 51820,
53
+ serverPublicKeys: manager.getServerPublicKeys(),
54
+ registeredClients: manager.listClients().length,
55
+ connectedClients: connected.length,
56
+ },
57
+ };
58
+ }));
59
+ // ---- Write endpoints (adminRouter — admin identity required via middleware) ----
60
+ // Create a new VPN client
61
+ adminRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('createVpnClient', async (dataArg, toolsArg) => {
62
+ const manager = this.opsServerRef.dcRouterRef.vpnManager;
63
+ if (!manager) {
64
+ return { success: false, message: 'VPN not configured' };
65
+ }
66
+ try {
67
+ const bundle = await manager.createClient({
68
+ clientId: dataArg.clientId,
69
+ serverDefinedClientTags: dataArg.serverDefinedClientTags,
70
+ description: dataArg.description,
71
+ });
72
+ return {
73
+ success: true,
74
+ client: {
75
+ clientId: bundle.entry.clientId,
76
+ enabled: bundle.entry.enabled ?? true,
77
+ serverDefinedClientTags: bundle.entry.serverDefinedClientTags,
78
+ description: bundle.entry.description,
79
+ assignedIp: bundle.entry.assignedIp,
80
+ createdAt: Date.now(),
81
+ updatedAt: Date.now(),
82
+ expiresAt: bundle.entry.expiresAt,
83
+ },
84
+ wireguardConfig: bundle.wireguardConfig,
85
+ };
86
+ }
87
+ catch (err) {
88
+ return { success: false, message: err.message };
89
+ }
90
+ }));
91
+ // Delete a VPN client
92
+ adminRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('deleteVpnClient', async (dataArg, toolsArg) => {
93
+ const manager = this.opsServerRef.dcRouterRef.vpnManager;
94
+ if (!manager) {
95
+ return { success: false, message: 'VPN not configured' };
96
+ }
97
+ try {
98
+ await manager.removeClient(dataArg.clientId);
99
+ return { success: true };
100
+ }
101
+ catch (err) {
102
+ return { success: false, message: err.message };
103
+ }
104
+ }));
105
+ // Enable a VPN client
106
+ adminRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('enableVpnClient', async (dataArg, toolsArg) => {
107
+ const manager = this.opsServerRef.dcRouterRef.vpnManager;
108
+ if (!manager) {
109
+ return { success: false, message: 'VPN not configured' };
110
+ }
111
+ try {
112
+ await manager.enableClient(dataArg.clientId);
113
+ return { success: true };
114
+ }
115
+ catch (err) {
116
+ return { success: false, message: err.message };
117
+ }
118
+ }));
119
+ // Disable a VPN client
120
+ adminRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('disableVpnClient', async (dataArg, toolsArg) => {
121
+ const manager = this.opsServerRef.dcRouterRef.vpnManager;
122
+ if (!manager) {
123
+ return { success: false, message: 'VPN not configured' };
124
+ }
125
+ try {
126
+ await manager.disableClient(dataArg.clientId);
127
+ return { success: true };
128
+ }
129
+ catch (err) {
130
+ return { success: false, message: err.message };
131
+ }
132
+ }));
133
+ // Rotate a VPN client's keys
134
+ adminRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('rotateVpnClientKey', async (dataArg, toolsArg) => {
135
+ const manager = this.opsServerRef.dcRouterRef.vpnManager;
136
+ if (!manager) {
137
+ return { success: false, message: 'VPN not configured' };
138
+ }
139
+ try {
140
+ const bundle = await manager.rotateClientKey(dataArg.clientId);
141
+ return {
142
+ success: true,
143
+ wireguardConfig: bundle.wireguardConfig,
144
+ };
145
+ }
146
+ catch (err) {
147
+ return { success: false, message: err.message };
148
+ }
149
+ }));
150
+ // Export a VPN client config
151
+ adminRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('exportVpnClientConfig', async (dataArg, toolsArg) => {
152
+ const manager = this.opsServerRef.dcRouterRef.vpnManager;
153
+ if (!manager) {
154
+ return { success: false, message: 'VPN not configured' };
155
+ }
156
+ try {
157
+ const config = await manager.exportClientConfig(dataArg.clientId, dataArg.format);
158
+ return { success: true, config };
159
+ }
160
+ catch (err) {
161
+ return { success: false, message: err.message };
162
+ }
163
+ }));
164
+ // Get telemetry for a specific VPN client
165
+ viewRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getVpnClientTelemetry', async (dataArg, toolsArg) => {
166
+ const manager = this.opsServerRef.dcRouterRef.vpnManager;
167
+ if (!manager) {
168
+ return { success: false, message: 'VPN not configured' };
169
+ }
170
+ try {
171
+ const telemetry = await manager.getClientTelemetry(dataArg.clientId);
172
+ if (!telemetry) {
173
+ return { success: false, message: 'Client not found or not connected' };
174
+ }
175
+ return {
176
+ success: true,
177
+ telemetry: {
178
+ clientId: telemetry.clientId,
179
+ assignedIp: telemetry.assignedIp,
180
+ bytesSent: telemetry.bytesSent,
181
+ bytesReceived: telemetry.bytesReceived,
182
+ packetsDropped: telemetry.packetsDropped,
183
+ bytesDropped: telemetry.bytesDropped,
184
+ lastKeepaliveAt: telemetry.lastKeepaliveAt,
185
+ keepalivesReceived: telemetry.keepalivesReceived,
186
+ rateLimitBytesPerSec: telemetry.rateLimitBytesPerSec,
187
+ burstBytes: telemetry.burstBytes,
188
+ },
189
+ };
190
+ }
191
+ catch (err) {
192
+ return { success: false, message: err.message };
193
+ }
194
+ }));
195
+ }
196
+ }
197
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidnBuLmhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9vcHNzZXJ2ZXIvaGFuZGxlcnMvdnBuLmhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUU1QyxPQUFPLEtBQUssVUFBVSxNQUFNLGlDQUFpQyxDQUFDO0FBRTlELE1BQU0sT0FBTyxVQUFVO0lBQ0Q7SUFBcEIsWUFBb0IsWUFBdUI7UUFBdkIsaUJBQVksR0FBWixZQUFZLENBQVc7UUFDekMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVPLGdCQUFnQjtRQUN0QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQztRQUNoRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQztRQUVsRCxpRkFBaUY7UUFFakYsaUNBQWlDO1FBQ2pDLFVBQVUsQ0FBQyxlQUFlLENBQ3hCLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQ25DLGVBQWUsRUFDZixLQUFLLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUFFO1lBQzFCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQztZQUN6RCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2IsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQztZQUN6QixDQUFDO1lBQ0QsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDaEQsUUFBUSxFQUFFLENBQUMsQ0FBQyxRQUFRO2dCQUNwQixPQUFPLEVBQUUsQ0FBQyxDQUFDLE9BQU87Z0JBQ2xCLHVCQUF1QixFQUFFLENBQUMsQ0FBQyx1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