@serve.zone/dcrouter 7.4.3 → 8.1.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 (110) hide show
  1. package/dist_serve/bundle.js +11567 -3516
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/classes.dcrouter.d.ts +9 -0
  4. package/dist_ts/classes.dcrouter.js +27 -1
  5. package/dist_ts/config/classes.api-token-manager.d.ts +38 -0
  6. package/dist_ts/config/classes.api-token-manager.js +134 -0
  7. package/dist_ts/config/classes.route-config-manager.d.ts +35 -0
  8. package/dist_ts/config/classes.route-config-manager.js +231 -0
  9. package/dist_ts/config/index.d.ts +2 -0
  10. package/dist_ts/config/index.js +3 -1
  11. package/dist_ts/opsserver/classes.opsserver.d.ts +2 -0
  12. package/dist_ts/opsserver/classes.opsserver.js +5 -1
  13. package/dist_ts/opsserver/handlers/{email-ops.handler.d.ts → api-token.handler.d.ts} +4 -4
  14. package/dist_ts/opsserver/handlers/api-token.handler.js +66 -0
  15. package/dist_ts/opsserver/handlers/index.d.ts +2 -0
  16. package/dist_ts/opsserver/handlers/index.js +3 -1
  17. package/dist_ts/opsserver/handlers/{radius.handler.d.ts → route-management.handler.d.ts} +6 -1
  18. package/dist_ts/opsserver/handlers/route-management.handler.js +117 -0
  19. package/dist_ts_interfaces/data/index.d.ts +1 -0
  20. package/dist_ts_interfaces/data/index.js +2 -1
  21. package/dist_ts_interfaces/data/route-management.d.ts +68 -0
  22. package/dist_ts_interfaces/data/route-management.js +2 -0
  23. package/dist_ts_interfaces/requests/api-tokens.d.ts +63 -0
  24. package/dist_ts_interfaces/requests/api-tokens.js +2 -0
  25. package/dist_ts_interfaces/requests/email-ops.d.ts +51 -108
  26. package/dist_ts_interfaces/requests/index.d.ts +2 -0
  27. package/dist_ts_interfaces/requests/index.js +3 -1
  28. package/dist_ts_interfaces/requests/route-management.d.ts +114 -0
  29. package/dist_ts_interfaces/requests/route-management.js +2 -0
  30. package/dist_ts_web/00_commitinfo_data.js +1 -1
  31. package/dist_ts_web/appstate.d.ts +38 -16
  32. package/dist_ts_web/appstate.js +226 -177
  33. package/dist_ts_web/elements/index.d.ts +2 -0
  34. package/dist_ts_web/elements/index.js +3 -1
  35. package/dist_ts_web/elements/ops-dashboard.js +11 -1
  36. package/dist_ts_web/elements/ops-view-apitokens.d.ts +12 -0
  37. package/dist_ts_web/elements/ops-view-apitokens.js +306 -0
  38. package/dist_ts_web/elements/ops-view-emails.d.ts +8 -31
  39. package/dist_ts_web/elements/ops-view-emails.js +54 -769
  40. package/dist_ts_web/elements/ops-view-logs.d.ts +2 -8
  41. package/dist_ts_web/elements/ops-view-logs.js +4 -101
  42. package/dist_ts_web/elements/ops-view-routes.d.ts +12 -0
  43. package/dist_ts_web/elements/ops-view-routes.js +404 -0
  44. package/dist_ts_web/plugins.d.ts +2 -1
  45. package/dist_ts_web/plugins.js +4 -2
  46. package/dist_ts_web/router.d.ts +1 -7
  47. package/dist_ts_web/router.js +8 -82
  48. package/package.json +2 -1
  49. package/ts/00_commitinfo_data.ts +1 -1
  50. package/ts/classes.dcrouter.ts +37 -1
  51. package/ts/config/classes.api-token-manager.ts +155 -0
  52. package/ts/config/classes.route-config-manager.ts +271 -0
  53. package/ts/config/index.ts +3 -1
  54. package/ts/opsserver/classes.opsserver.ts +4 -0
  55. package/ts/opsserver/handlers/api-token.handler.ts +96 -0
  56. package/ts/opsserver/handlers/email-ops.handler.ts +177 -225
  57. package/ts/opsserver/handlers/index.ts +3 -1
  58. package/ts/opsserver/handlers/route-management.handler.ts +163 -0
  59. package/ts_web/00_commitinfo_data.ts +1 -1
  60. package/ts_web/appstate.ts +316 -222
  61. package/ts_web/elements/index.ts +2 -0
  62. package/ts_web/elements/ops-dashboard.ts +10 -0
  63. package/ts_web/elements/ops-view-apitokens.ts +281 -0
  64. package/ts_web/elements/ops-view-emails.ts +40 -749
  65. package/ts_web/elements/ops-view-logs.ts +2 -87
  66. package/ts_web/elements/ops-view-routes.ts +389 -0
  67. package/ts_web/plugins.ts +4 -0
  68. package/ts_web/router.ts +7 -82
  69. package/dist_ts/cache/classes.cache.cleaner.d.ts +0 -47
  70. package/dist_ts/cache/classes.cache.cleaner.js +0 -130
  71. package/dist_ts/cache/classes.cached.document.d.ts +0 -76
  72. package/dist_ts/cache/classes.cached.document.js +0 -100
  73. package/dist_ts/cache/classes.cachedb.d.ts +0 -60
  74. package/dist_ts/cache/classes.cachedb.js +0 -126
  75. package/dist_ts/cache/documents/classes.cached.email.d.ts +0 -125
  76. package/dist_ts/cache/documents/classes.cached.email.js +0 -337
  77. package/dist_ts/cache/documents/classes.cached.ip.reputation.d.ts +0 -119
  78. package/dist_ts/cache/documents/classes.cached.ip.reputation.js +0 -323
  79. package/dist_ts/cache/documents/index.d.ts +0 -2
  80. package/dist_ts/cache/documents/index.js +0 -3
  81. package/dist_ts/cache/index.d.ts +0 -4
  82. package/dist_ts/cache/index.js +0 -7
  83. package/dist_ts/monitoring/classes.metricscache.d.ts +0 -32
  84. package/dist_ts/monitoring/classes.metricscache.js +0 -63
  85. package/dist_ts/monitoring/classes.metricsmanager.d.ts +0 -169
  86. package/dist_ts/monitoring/classes.metricsmanager.js +0 -591
  87. package/dist_ts/monitoring/index.d.ts +0 -1
  88. package/dist_ts/monitoring/index.js +0 -2
  89. package/dist_ts/opsserver/handlers/admin.handler.d.ts +0 -31
  90. package/dist_ts/opsserver/handlers/admin.handler.js +0 -180
  91. package/dist_ts/opsserver/handlers/certificate.handler.d.ts +0 -34
  92. package/dist_ts/opsserver/handlers/certificate.handler.js +0 -419
  93. package/dist_ts/opsserver/handlers/config.handler.d.ts +0 -9
  94. package/dist_ts/opsserver/handlers/config.handler.js +0 -67
  95. package/dist_ts/opsserver/handlers/email-ops.handler.js +0 -219
  96. package/dist_ts/opsserver/handlers/logs.handler.d.ts +0 -17
  97. package/dist_ts/opsserver/handlers/logs.handler.js +0 -215
  98. package/dist_ts/opsserver/handlers/radius.handler.js +0 -296
  99. package/dist_ts/opsserver/handlers/remoteingress.handler.d.ts +0 -8
  100. package/dist_ts/opsserver/handlers/remoteingress.handler.js +0 -154
  101. package/dist_ts/opsserver/handlers/security.handler.d.ts +0 -11
  102. package/dist_ts/opsserver/handlers/security.handler.js +0 -232
  103. package/dist_ts/opsserver/handlers/stats.handler.d.ts +0 -13
  104. package/dist_ts/opsserver/handlers/stats.handler.js +0 -400
  105. package/dist_ts/security/classes.securitylogger.d.ts +0 -140
  106. package/dist_ts/security/classes.securitylogger.js +0 -235
  107. package/dist_ts/storage/classes.storagemanager.d.ts +0 -82
  108. package/dist_ts/storage/classes.storagemanager.js +0 -344
  109. package/dist_ts/storage/index.d.ts +0 -1
  110. package/dist_ts/storage/index.js +0 -3
@@ -1,219 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import * as interfaces from '../../../dist_ts_interfaces/index.js';
3
- import { SecurityLogger } from '../../security/index.js';
4
- export class EmailOpsHandler {
5
- opsServerRef;
6
- typedrouter = new plugins.typedrequest.TypedRouter();
7
- constructor(opsServerRef) {
8
- this.opsServerRef = opsServerRef;
9
- // Add this handler's router to the parent
10
- this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
11
- this.registerHandlers();
12
- }
13
- registerHandlers() {
14
- // Get Queued Emails Handler
15
- this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getQueuedEmails', async (dataArg) => {
16
- const emailServer = this.opsServerRef.dcRouterRef.emailServer;
17
- if (!emailServer?.deliveryQueue) {
18
- return { items: [], total: 0 };
19
- }
20
- const queue = emailServer.deliveryQueue;
21
- const stats = queue.getStats();
22
- // Get all queue items and filter by status if provided
23
- const items = this.getQueueItems(dataArg.status, dataArg.limit || 50, dataArg.offset || 0);
24
- return {
25
- items,
26
- total: stats.queueSize,
27
- };
28
- }));
29
- // Get Sent Emails Handler
30
- this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getSentEmails', async (dataArg) => {
31
- const items = this.getQueueItems('delivered', dataArg.limit || 50, dataArg.offset || 0);
32
- return {
33
- items,
34
- total: items.length, // Note: total would ideally come from a counter
35
- };
36
- }));
37
- // Get Failed Emails Handler
38
- this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getFailedEmails', async (dataArg) => {
39
- const items = this.getQueueItems('failed', dataArg.limit || 50, dataArg.offset || 0);
40
- return {
41
- items,
42
- total: items.length,
43
- };
44
- }));
45
- // Resend Failed Email Handler
46
- this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('resendEmail', async (dataArg) => {
47
- const emailServer = this.opsServerRef.dcRouterRef.emailServer;
48
- if (!emailServer?.deliveryQueue) {
49
- return { success: false, error: 'Email server not available' };
50
- }
51
- const queue = emailServer.deliveryQueue;
52
- const item = queue.getItem(dataArg.emailId);
53
- if (!item) {
54
- return { success: false, error: 'Email not found in queue' };
55
- }
56
- if (item.status !== 'failed') {
57
- return { success: false, error: `Email is not in failed state (current: ${item.status})` };
58
- }
59
- try {
60
- // Re-enqueue the failed email by creating a new queue entry
61
- // with the same data but reset attempt count
62
- const newQueueId = await queue.enqueue(item.processingResult, item.processingMode, item.route);
63
- // Optionally remove the old failed entry
64
- await queue.removeItem(dataArg.emailId);
65
- return { success: true, newQueueId };
66
- }
67
- catch (error) {
68
- return {
69
- success: false,
70
- error: error instanceof Error ? error.message : 'Failed to resend email'
71
- };
72
- }
73
- }));
74
- // Get Security Incidents Handler
75
- this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getSecurityIncidents', async (dataArg) => {
76
- const securityLogger = SecurityLogger.getInstance();
77
- const filter = {};
78
- if (dataArg.level) {
79
- filter.level = dataArg.level;
80
- }
81
- if (dataArg.type) {
82
- filter.type = dataArg.type;
83
- }
84
- const incidents = securityLogger.getRecentEvents(dataArg.limit || 100, Object.keys(filter).length > 0 ? filter : undefined);
85
- return {
86
- incidents: incidents.map(event => ({
87
- timestamp: event.timestamp,
88
- level: event.level,
89
- type: event.type,
90
- message: event.message,
91
- details: event.details,
92
- ipAddress: event.ipAddress,
93
- userId: event.userId,
94
- sessionId: event.sessionId,
95
- emailId: event.emailId,
96
- domain: event.domain,
97
- action: event.action,
98
- result: event.result,
99
- success: event.success,
100
- })),
101
- total: incidents.length,
102
- };
103
- }));
104
- // Get Bounce Records Handler
105
- this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getBounceRecords', async (dataArg) => {
106
- const emailServer = this.opsServerRef.dcRouterRef.emailServer;
107
- if (!emailServer) {
108
- return { records: [], suppressionList: [], total: 0 };
109
- }
110
- // Use smartmta's public API for bounce/suppression data
111
- const suppressionList = emailServer.getSuppressionList();
112
- const hardBouncedAddresses = emailServer.getHardBouncedAddresses();
113
- // Create bounce records from the available data
114
- const records = [];
115
- for (const email of hardBouncedAddresses) {
116
- const bounceInfo = emailServer.getBounceHistory(email);
117
- if (bounceInfo) {
118
- records.push({
119
- id: `bounce-${email}`,
120
- recipient: email,
121
- sender: '',
122
- domain: email.split('@')[1] || '',
123
- bounceType: bounceInfo.type,
124
- bounceCategory: bounceInfo.category,
125
- timestamp: bounceInfo.lastBounce,
126
- processed: true,
127
- });
128
- }
129
- }
130
- // Apply limit and offset
131
- const limit = dataArg.limit || 50;
132
- const offset = dataArg.offset || 0;
133
- const paginatedRecords = records.slice(offset, offset + limit);
134
- return {
135
- records: paginatedRecords,
136
- suppressionList,
137
- total: records.length,
138
- };
139
- }));
140
- // Remove from Suppression List Handler
141
- this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('removeFromSuppressionList', async (dataArg) => {
142
- const emailServer = this.opsServerRef.dcRouterRef.emailServer;
143
- if (!emailServer) {
144
- return { success: false, error: 'Email server not available' };
145
- }
146
- try {
147
- emailServer.removeFromSuppressionList(dataArg.email);
148
- return { success: true };
149
- }
150
- catch (error) {
151
- return {
152
- success: false,
153
- error: error instanceof Error ? error.message : 'Failed to remove from suppression list'
154
- };
155
- }
156
- }));
157
- }
158
- /**
159
- * Helper method to get queue items with filtering and pagination
160
- */
161
- getQueueItems(status, limit = 50, offset = 0) {
162
- const emailServer = this.opsServerRef.dcRouterRef.emailServer;
163
- if (!emailServer?.deliveryQueue) {
164
- return [];
165
- }
166
- const queue = emailServer.deliveryQueue;
167
- const items = [];
168
- // Access the internal queue map via reflection
169
- // This is necessary because the queue doesn't expose iteration methods
170
- const queueMap = queue.queue;
171
- if (!queueMap) {
172
- return [];
173
- }
174
- // Filter and convert items
175
- for (const [id, item] of queueMap.entries()) {
176
- // Apply status filter if provided
177
- if (status && item.status !== status) {
178
- continue;
179
- }
180
- // Extract email details from processingResult if available
181
- const processingResult = item.processingResult;
182
- let from = '';
183
- let to = [];
184
- let subject = '';
185
- if (processingResult) {
186
- // Check if it's an Email object or raw email data
187
- if (processingResult.email) {
188
- from = processingResult.email.from || '';
189
- to = processingResult.email.to || [];
190
- subject = processingResult.email.subject || '';
191
- }
192
- else if (processingResult.from) {
193
- from = processingResult.from;
194
- to = processingResult.to || [];
195
- subject = processingResult.subject || '';
196
- }
197
- }
198
- items.push({
199
- id: item.id,
200
- processingMode: item.processingMode,
201
- status: item.status,
202
- attempts: item.attempts,
203
- nextAttempt: item.nextAttempt instanceof Date ? item.nextAttempt.getTime() : item.nextAttempt,
204
- lastError: item.lastError,
205
- createdAt: item.createdAt instanceof Date ? item.createdAt.getTime() : item.createdAt,
206
- updatedAt: item.updatedAt instanceof Date ? item.updatedAt.getTime() : item.updatedAt,
207
- deliveredAt: item.deliveredAt instanceof Date ? item.deliveredAt.getTime() : item.deliveredAt,
208
- from,
209
- to,
210
- subject,
211
- });
212
- }
213
- // Sort by createdAt descending (newest first)
214
- items.sort((a, b) => b.createdAt - a.createdAt);
215
- // Apply pagination
216
- return items.slice(offset, offset + limit);
217
- }
218
- }
219
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1haWwtb3BzLmhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9vcHNzZXJ2ZXIvaGFuZGxlcnMvZW1haWwtb3BzLmhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUU1QyxPQUFPLEtBQUssVUFBVSxNQUFNLGlDQUFpQyxDQUFDO0FBQzlELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV6RCxNQUFNLE9BQU8sZUFBZTtJQUdOO0lBRmIsV0FBVyxHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUU1RCxZQUFvQixZQUF1QjtRQUF2QixpQkFBWSxHQUFaLFlBQVksQ0FBVztRQUN6QywwQ0FBMEM7UUFDMUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRU8sZ0JBQWdCO1FBQ3RCLDRCQUE0QjtRQUM1QixJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FDOUIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDbkMsaUJBQWlCLEVBQ2pCLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtZQUNoQixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUM7WUFDOUQsSUFBSSxDQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsQ0FBQztnQkFDaEMsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ2pDLENBQUM7WUFFRCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsYUFBYSxDQUFDO1lBQ3hDLE1BQU0sS0FBSyxHQUFHLEtBQUss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
@@ -1,17 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import type { OpsServer } from '../classes.opsserver.js';
3
- export declare class LogsHandler {
4
- private opsServerRef;
5
- typedrouter: plugins.typedrequest.TypedRouter;
6
- constructor(opsServerRef: OpsServer);
7
- private registerHandlers;
8
- private static mapLogLevel;
9
- private static deriveCategory;
10
- private getRecentLogs;
11
- /**
12
- * Add a log destination to the base logger that pushes entries
13
- * to all connected ops_dashboard TypedSocket clients.
14
- */
15
- private setupLogPushDestination;
16
- private setupLogStream;
17
- }
@@ -1,215 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import * as interfaces from '../../../dist_ts_interfaces/index.js';
3
- import { logBuffer, baseLogger } from '../../logger.js';
4
- export class LogsHandler {
5
- opsServerRef;
6
- typedrouter = new plugins.typedrequest.TypedRouter();
7
- constructor(opsServerRef) {
8
- this.opsServerRef = opsServerRef;
9
- // Add this handler's router to the parent
10
- this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
11
- this.registerHandlers();
12
- this.setupLogPushDestination();
13
- }
14
- registerHandlers() {
15
- // Get Recent Logs Handler
16
- this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getRecentLogs', async (dataArg, toolsArg) => {
17
- const logs = await this.getRecentLogs(dataArg.level, dataArg.category, dataArg.limit || 100, dataArg.offset || 0, dataArg.search, dataArg.timeRange);
18
- return {
19
- logs,
20
- total: logs.length, // TODO: Implement proper total count
21
- hasMore: false, // TODO: Implement proper pagination
22
- };
23
- }));
24
- // Get Log Stream Handler
25
- this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getLogStream', async (dataArg, toolsArg) => {
26
- // Create a virtual stream for log streaming
27
- const virtualStream = new plugins.typedrequest.VirtualStream();
28
- // Set up log streaming
29
- const streamLogs = this.setupLogStream(virtualStream, dataArg.filters?.level, dataArg.filters?.category, dataArg.follow);
30
- // Start streaming
31
- streamLogs.start();
32
- // VirtualStream handles cleanup automatically
33
- return {
34
- logStream: virtualStream, // Cast to IVirtualStream interface
35
- };
36
- }));
37
- }
38
- static mapLogLevel(smartlogLevel) {
39
- switch (smartlogLevel) {
40
- case 'silly':
41
- case 'debug':
42
- return 'debug';
43
- case 'warn':
44
- return 'warn';
45
- case 'error':
46
- return 'error';
47
- default:
48
- return 'info';
49
- }
50
- }
51
- static deriveCategory(zone, message) {
52
- const msg = (message || '').toLowerCase();
53
- if (msg.includes('[security:') || msg.includes('security'))
54
- return 'security';
55
- if (zone === 'email' || msg.includes('email') || msg.includes('smtp') || msg.includes('mta'))
56
- return 'email';
57
- if (zone === 'dns' || msg.includes('dns'))
58
- return 'dns';
59
- if (msg.includes('smtp'))
60
- return 'smtp';
61
- return 'system';
62
- }
63
- async getRecentLogs(level, category, limit = 100, offset = 0, search, timeRange) {
64
- // Compute a timestamp cutoff from timeRange
65
- let since;
66
- if (timeRange) {
67
- const rangeMs = {
68
- '1h': 3600000,
69
- '6h': 21600000,
70
- '24h': 86400000,
71
- '7d': 604800000,
72
- '30d': 2592000000,
73
- };
74
- since = Date.now() - (rangeMs[timeRange] || 86400000);
75
- }
76
- // Map the UI level to smartlog levels for filtering
77
- const smartlogLevels = level
78
- ? level === 'debug'
79
- ? ['debug', 'silly']
80
- : level === 'info'
81
- ? ['info', 'ok', 'success', 'note', 'lifecycle']
82
- : [level]
83
- : undefined;
84
- // Fetch a larger batch from buffer, then apply category filter client-side
85
- const rawEntries = logBuffer.getEntries({
86
- level: smartlogLevels,
87
- search,
88
- since,
89
- limit: limit * 3, // over-fetch to compensate for category filtering
90
- offset: 0,
91
- });
92
- // Map ILogPackage → UI log format and apply category filter
93
- const mapped = [];
94
- for (const pkg of rawEntries) {
95
- const uiLevel = LogsHandler.mapLogLevel(pkg.level);
96
- const uiCategory = LogsHandler.deriveCategory(pkg.context?.zone, pkg.message);
97
- if (category && uiCategory !== category)
98
- continue;
99
- mapped.push({
100
- timestamp: pkg.timestamp,
101
- level: uiLevel,
102
- category: uiCategory,
103
- message: pkg.message,
104
- metadata: pkg.data,
105
- });
106
- if (mapped.length >= limit)
107
- break;
108
- }
109
- return mapped;
110
- }
111
- /**
112
- * Add a log destination to the base logger that pushes entries
113
- * to all connected ops_dashboard TypedSocket clients.
114
- */
115
- setupLogPushDestination() {
116
- const opsServerRef = this.opsServerRef;
117
- baseLogger.addLogDestination({
118
- async handleLog(logPackage) {
119
- // Access the TypedSocket server instance from OpsServer
120
- const typedsocket = opsServerRef.server?.typedserver?.typedsocket;
121
- if (!typedsocket)
122
- return;
123
- let connections;
124
- try {
125
- connections = await typedsocket.findAllTargetConnectionsByTag('role', 'ops_dashboard');
126
- }
127
- catch {
128
- return;
129
- }
130
- if (connections.length === 0)
131
- return;
132
- const entry = {
133
- timestamp: logPackage.timestamp || Date.now(),
134
- level: LogsHandler.mapLogLevel(logPackage.level),
135
- category: LogsHandler.deriveCategory(logPackage.context?.zone, logPackage.message),
136
- message: logPackage.message,
137
- metadata: logPackage.data,
138
- };
139
- for (const conn of connections) {
140
- try {
141
- const push = typedsocket.createTypedRequest('pushLogEntry', conn);
142
- push.fire({ entry }).catch(() => { }); // fire-and-forget
143
- }
144
- catch {
145
- // connection may have closed
146
- }
147
- }
148
- },
149
- });
150
- }
151
- setupLogStream(virtualStream, levelFilter, categoryFilter, follow = true) {
152
- let intervalId = null;
153
- let logIndex = 0;
154
- const start = () => {
155
- if (!follow) {
156
- // Send existing logs and close
157
- this.getRecentLogs(levelFilter?.[0], categoryFilter?.[0], 100, 0).then(logs => {
158
- logs.forEach(log => {
159
- const logData = JSON.stringify(log);
160
- const encoder = new TextEncoder();
161
- virtualStream.sendData(encoder.encode(logData));
162
- });
163
- // VirtualStream doesn't have end() method - it closes automatically
164
- });
165
- return;
166
- }
167
- // For follow mode, simulate real-time log streaming
168
- intervalId = setInterval(async () => {
169
- const categories = ['smtp', 'dns', 'security', 'system', 'email'];
170
- const levels = ['info', 'warn', 'error', 'debug'];
171
- const mockCategory = categories[Math.floor(Math.random() * categories.length)];
172
- const mockLevel = levels[Math.floor(Math.random() * levels.length)];
173
- // Filter by requested criteria
174
- if (levelFilter && !levelFilter.includes(mockLevel))
175
- return;
176
- if (categoryFilter && !categoryFilter.includes(mockCategory))
177
- return;
178
- const logEntry = {
179
- timestamp: Date.now(),
180
- level: mockLevel,
181
- category: mockCategory,
182
- message: `Real-time log ${logIndex++} from ${mockCategory}`,
183
- metadata: {
184
- requestId: plugins.uuid.v4(),
185
- },
186
- };
187
- const logData = JSON.stringify(logEntry);
188
- const encoder = new TextEncoder();
189
- try {
190
- await virtualStream.sendData(encoder.encode(logData));
191
- }
192
- catch {
193
- // Stream closed or errored — clean up to prevent interval leak
194
- clearInterval(intervalId);
195
- intervalId = null;
196
- }
197
- }, 2000); // Send a log every 2 seconds
198
- // TODO: Hook into actual logger events
199
- // logger.on('log', (logEntry) => {
200
- // if (matchesCriteria(logEntry, level, service)) {
201
- // virtualStream.sendData(formatLogEntry(logEntry));
202
- // }
203
- // });
204
- };
205
- const stop = () => {
206
- if (intervalId) {
207
- clearInterval(intervalId);
208
- intervalId = null;
209
- }
210
- // TODO: Unhook from logger events
211
- };
212
- return { start, stop };
213
- }
214
- }
215
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9ncy5oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvb3Bzc2VydmVyL2hhbmRsZXJzL2xvZ3MuaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBRTVDLE9BQU8sS0FBSyxVQUFVLE1BQU0saUNBQWlDLENBQUM7QUFDOUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV4RCxNQUFNLE9BQU8sV0FBVztJQUdGO0lBRmIsV0FBVyxHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUU1RCxZQUFvQixZQUF1QjtRQUF2QixpQkFBWSxHQUFaLFlBQVksQ0FBVztRQUN6QywwQ0FBMEM7UUFDMUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztJQUNqQyxDQUFDO0lBRU8sZ0JBQWdCO1FBQ3RCLDBCQUEwQjtRQUMxQixJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FDOUIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDbkMsZUFBZSxFQUNmLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEVBQUU7WUFDMUIsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUNuQyxPQUFPLENBQUMsS0FBSyxFQUNiLE9BQU8sQ0FBQyxRQUFRLEVBQ2hCLE9BQU8sQ0FBQyxLQUFLLElBQUksR0FBRyxFQUNwQixPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsRUFDbkIsT0FBTyxDQUFDLE1BQU0sRUFDZCxPQUFPLENBQUMsU0FBUyxDQUNsQixDQUFDO1lBRUYs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