@serve.zone/dcrouter 11.0.38 → 11.0.39
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/dist_serve/bundle.js +1 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/package.json +2 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/dist_ts/cache/classes.cache.cleaner.d.ts +0 -47
- package/dist_ts/cache/classes.cache.cleaner.js +0 -130
- package/dist_ts/cache/documents/classes.cached.email.d.ts +0 -125
- package/dist_ts/cache/documents/classes.cached.email.js +0 -337
- package/dist_ts/cache/documents/classes.cached.ip.reputation.d.ts +0 -119
- package/dist_ts/cache/documents/classes.cached.ip.reputation.js +0 -323
- package/dist_ts/cache/documents/index.d.ts +0 -2
- package/dist_ts/cache/documents/index.js +0 -3
- package/dist_ts/cache/index.d.ts +0 -4
- package/dist_ts/cache/index.js +0 -7
- package/dist_ts/classes.cert-provision-scheduler.d.ts +0 -53
- package/dist_ts/classes.cert-provision-scheduler.js +0 -110
- package/dist_ts/classes.storage-cert-manager.d.ts +0 -18
- package/dist_ts/classes.storage-cert-manager.js +0 -43
- package/dist_ts/errors/base.errors.js +0 -320
- package/dist_ts/errors/error.codes.d.ts +0 -115
- package/dist_ts/errors/error.codes.js +0 -136
- package/dist_ts/monitoring/classes.metricscache.d.ts +0 -32
- package/dist_ts/monitoring/classes.metricscache.js +0 -63
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +0 -178
- package/dist_ts/monitoring/classes.metricsmanager.js +0 -642
- package/dist_ts/monitoring/index.d.ts +0 -1
- package/dist_ts/monitoring/index.js +0 -2
- package/dist_ts/opsserver/classes.opsserver.d.ts +0 -37
- package/dist_ts/opsserver/classes.opsserver.js +0 -85
- package/dist_ts/opsserver/handlers/admin.handler.d.ts +0 -31
- package/dist_ts/opsserver/handlers/admin.handler.js +0 -180
- package/dist_ts/opsserver/handlers/api-token.handler.d.ts +0 -6
- package/dist_ts/opsserver/handlers/api-token.handler.js +0 -62
- package/dist_ts/opsserver/handlers/certificate.handler.d.ts +0 -32
- package/dist_ts/opsserver/handlers/certificate.handler.js +0 -421
- package/dist_ts/opsserver/handlers/config.handler.d.ts +0 -7
- package/dist_ts/opsserver/handlers/config.handler.js +0 -192
- package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +0 -30
- package/dist_ts/opsserver/handlers/email-ops.handler.js +0 -227
- package/dist_ts/opsserver/handlers/index.d.ts +0 -11
- package/dist_ts/opsserver/handlers/index.js +0 -12
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +0 -25
- package/dist_ts/opsserver/handlers/logs.handler.js +0 -256
- package/dist_ts/opsserver/handlers/radius.handler.d.ts +0 -6
- package/dist_ts/opsserver/handlers/radius.handler.js +0 -295
- package/dist_ts/opsserver/handlers/remoteingress.handler.d.ts +0 -6
- package/dist_ts/opsserver/handlers/remoteingress.handler.js +0 -156
- package/dist_ts/opsserver/handlers/route-management.handler.d.ts +0 -14
- package/dist_ts/opsserver/handlers/route-management.handler.js +0 -117
- package/dist_ts/opsserver/handlers/security.handler.d.ts +0 -9
- package/dist_ts/opsserver/handlers/security.handler.js +0 -231
- package/dist_ts/opsserver/handlers/stats.handler.d.ts +0 -11
- package/dist_ts/opsserver/handlers/stats.handler.js +0 -399
- package/dist_ts/opsserver/helpers/guards.d.ts +0 -27
- package/dist_ts/opsserver/helpers/guards.js +0 -43
- package/dist_ts/opsserver/index.d.ts +0 -1
- package/dist_ts/opsserver/index.js +0 -2
- package/dist_ts/radius/classes.accounting.manager.d.ts +0 -218
- package/dist_ts/radius/classes.accounting.manager.js +0 -417
- package/dist_ts/radius/classes.radius.server.d.ts +0 -171
- package/dist_ts/radius/classes.radius.server.js +0 -385
- package/dist_ts/radius/classes.vlan.manager.d.ts +0 -128
- package/dist_ts/radius/classes.vlan.manager.js +0 -279
- package/dist_ts/radius/index.d.ts +0 -13
- package/dist_ts/radius/index.js +0 -14
- package/dist_ts/remoteingress/classes.remoteingress-manager.d.ts +0 -82
- package/dist_ts/remoteingress/classes.remoteingress-manager.js +0 -227
- package/dist_ts/remoteingress/classes.tunnel-manager.d.ts +0 -59
- package/dist_ts/remoteingress/classes.tunnel-manager.js +0 -165
- package/dist_ts/remoteingress/index.d.ts +0 -2
- package/dist_ts/remoteingress/index.js +0 -3
- package/dist_ts/security/classes.securitylogger.d.ts +0 -144
- package/dist_ts/security/classes.securitylogger.js +0 -233
- package/dist_ts/storage/classes.storagemanager.d.ts +0 -83
- package/dist_ts/storage/classes.storagemanager.js +0 -350
- package/dist_ts/storage/index.d.ts +0 -1
- package/dist_ts/storage/index.js +0 -3
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { OpsServer } from '../classes.opsserver.js';
|
|
2
|
-
export declare class EmailOpsHandler {
|
|
3
|
-
private opsServerRef;
|
|
4
|
-
constructor(opsServerRef: OpsServer);
|
|
5
|
-
private registerHandlers;
|
|
6
|
-
/**
|
|
7
|
-
* Get all queue items mapped to catalog IEmail format
|
|
8
|
-
*/
|
|
9
|
-
private getAllQueueEmails;
|
|
10
|
-
/**
|
|
11
|
-
* Get a single email detail by ID
|
|
12
|
-
*/
|
|
13
|
-
private getEmailDetail;
|
|
14
|
-
/**
|
|
15
|
-
* Map a queue item to catalog IEmail format
|
|
16
|
-
*/
|
|
17
|
-
private mapQueueItemToEmail;
|
|
18
|
-
/**
|
|
19
|
-
* Map a queue item to catalog IEmailDetail format
|
|
20
|
-
*/
|
|
21
|
-
private mapQueueItemToEmailDetail;
|
|
22
|
-
/**
|
|
23
|
-
* Map queue status to catalog TEmailStatus
|
|
24
|
-
*/
|
|
25
|
-
private mapStatus;
|
|
26
|
-
/**
|
|
27
|
-
* Format byte size to human-readable string
|
|
28
|
-
*/
|
|
29
|
-
private formatSize;
|
|
30
|
-
}
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import * as plugins from '../../plugins.js';
|
|
2
|
-
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
3
|
-
export class EmailOpsHandler {
|
|
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 Emails Handler
|
|
14
|
-
viewRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getAllEmails', async (dataArg) => {
|
|
15
|
-
const emails = this.getAllQueueEmails();
|
|
16
|
-
return { emails };
|
|
17
|
-
}));
|
|
18
|
-
// Get Email Detail Handler
|
|
19
|
-
viewRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getEmailDetail', async (dataArg) => {
|
|
20
|
-
const email = this.getEmailDetail(dataArg.emailId);
|
|
21
|
-
return { email };
|
|
22
|
-
}));
|
|
23
|
-
// ---- Write endpoints (adminRouter) ----
|
|
24
|
-
// Resend Failed Email Handler
|
|
25
|
-
adminRouter.addTypedHandler(new plugins.typedrequest.TypedHandler('resendEmail', async (dataArg) => {
|
|
26
|
-
const emailServer = this.opsServerRef.dcRouterRef.emailServer;
|
|
27
|
-
if (!emailServer?.deliveryQueue) {
|
|
28
|
-
return { success: false, error: 'Email server not available' };
|
|
29
|
-
}
|
|
30
|
-
const queue = emailServer.deliveryQueue;
|
|
31
|
-
const item = queue.getItem(dataArg.emailId);
|
|
32
|
-
if (!item) {
|
|
33
|
-
return { success: false, error: 'Email not found in queue' };
|
|
34
|
-
}
|
|
35
|
-
if (item.status !== 'failed') {
|
|
36
|
-
return { success: false, error: `Email is not in failed state (current: ${item.status})` };
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
const newQueueId = await queue.enqueue(item.processingResult, item.processingMode, item.route);
|
|
40
|
-
await queue.removeItem(dataArg.emailId);
|
|
41
|
-
return { success: true, newQueueId };
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
return {
|
|
45
|
-
success: false,
|
|
46
|
-
error: error instanceof Error ? error.message : 'Failed to resend email'
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
}));
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Get all queue items mapped to catalog IEmail format
|
|
53
|
-
*/
|
|
54
|
-
getAllQueueEmails() {
|
|
55
|
-
const emailServer = this.opsServerRef.dcRouterRef.emailServer;
|
|
56
|
-
if (!emailServer?.deliveryQueue) {
|
|
57
|
-
return [];
|
|
58
|
-
}
|
|
59
|
-
const queue = emailServer.deliveryQueue;
|
|
60
|
-
const queueMap = queue.queue;
|
|
61
|
-
if (!queueMap) {
|
|
62
|
-
return [];
|
|
63
|
-
}
|
|
64
|
-
const emails = [];
|
|
65
|
-
for (const [id, item] of queueMap.entries()) {
|
|
66
|
-
emails.push(this.mapQueueItemToEmail(item));
|
|
67
|
-
}
|
|
68
|
-
// Sort by createdAt descending (newest first)
|
|
69
|
-
emails.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
70
|
-
return emails;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Get a single email detail by ID
|
|
74
|
-
*/
|
|
75
|
-
getEmailDetail(emailId) {
|
|
76
|
-
const emailServer = this.opsServerRef.dcRouterRef.emailServer;
|
|
77
|
-
if (!emailServer?.deliveryQueue) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
const queue = emailServer.deliveryQueue;
|
|
81
|
-
const item = queue.getItem(emailId);
|
|
82
|
-
if (!item) {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
return this.mapQueueItemToEmailDetail(item);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Map a queue item to catalog IEmail format
|
|
89
|
-
*/
|
|
90
|
-
mapQueueItemToEmail(item) {
|
|
91
|
-
const processingResult = item.processingResult;
|
|
92
|
-
let from = '';
|
|
93
|
-
let to = '';
|
|
94
|
-
let subject = '';
|
|
95
|
-
let messageId = '';
|
|
96
|
-
let size = '0 B';
|
|
97
|
-
if (processingResult) {
|
|
98
|
-
if (processingResult.email) {
|
|
99
|
-
from = processingResult.email.from || '';
|
|
100
|
-
to = (processingResult.email.to || [])[0] || '';
|
|
101
|
-
subject = processingResult.email.subject || '';
|
|
102
|
-
}
|
|
103
|
-
else if (processingResult.from) {
|
|
104
|
-
from = processingResult.from;
|
|
105
|
-
to = (processingResult.to || [])[0] || '';
|
|
106
|
-
subject = processingResult.subject || '';
|
|
107
|
-
}
|
|
108
|
-
// Try to get messageId
|
|
109
|
-
if (typeof processingResult.getMessageId === 'function') {
|
|
110
|
-
try {
|
|
111
|
-
messageId = processingResult.getMessageId() || '';
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
messageId = '';
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
// Compute approximate size
|
|
118
|
-
const textLen = processingResult.text?.length || 0;
|
|
119
|
-
const htmlLen = processingResult.html?.length || 0;
|
|
120
|
-
let attachSize = 0;
|
|
121
|
-
if (typeof processingResult.getAttachmentsSize === 'function') {
|
|
122
|
-
try {
|
|
123
|
-
attachSize = processingResult.getAttachmentsSize() || 0;
|
|
124
|
-
}
|
|
125
|
-
catch {
|
|
126
|
-
attachSize = 0;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
size = this.formatSize(textLen + htmlLen + attachSize);
|
|
130
|
-
}
|
|
131
|
-
// Map queue status to catalog TEmailStatus
|
|
132
|
-
const status = this.mapStatus(item.status);
|
|
133
|
-
const createdAt = item.createdAt instanceof Date ? item.createdAt.getTime() : item.createdAt;
|
|
134
|
-
return {
|
|
135
|
-
id: item.id,
|
|
136
|
-
direction: 'outbound',
|
|
137
|
-
status,
|
|
138
|
-
from,
|
|
139
|
-
to,
|
|
140
|
-
subject,
|
|
141
|
-
timestamp: new Date(createdAt).toISOString(),
|
|
142
|
-
messageId,
|
|
143
|
-
size,
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Map a queue item to catalog IEmailDetail format
|
|
148
|
-
*/
|
|
149
|
-
mapQueueItemToEmailDetail(item) {
|
|
150
|
-
const base = this.mapQueueItemToEmail(item);
|
|
151
|
-
const processingResult = item.processingResult;
|
|
152
|
-
let toList = [];
|
|
153
|
-
let cc = [];
|
|
154
|
-
let headers = {};
|
|
155
|
-
let body = '';
|
|
156
|
-
if (processingResult) {
|
|
157
|
-
if (processingResult.email) {
|
|
158
|
-
toList = processingResult.email.to || [];
|
|
159
|
-
cc = processingResult.email.cc || [];
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
toList = processingResult.to || [];
|
|
163
|
-
cc = processingResult.cc || [];
|
|
164
|
-
}
|
|
165
|
-
headers = processingResult.headers || {};
|
|
166
|
-
body = processingResult.html || processingResult.text || '';
|
|
167
|
-
}
|
|
168
|
-
return {
|
|
169
|
-
...base,
|
|
170
|
-
toList,
|
|
171
|
-
cc,
|
|
172
|
-
smtpLog: [],
|
|
173
|
-
connectionInfo: {
|
|
174
|
-
sourceIp: '',
|
|
175
|
-
sourceHostname: '',
|
|
176
|
-
destinationIp: '',
|
|
177
|
-
destinationPort: 0,
|
|
178
|
-
tlsVersion: '',
|
|
179
|
-
tlsCipher: '',
|
|
180
|
-
authenticated: false,
|
|
181
|
-
authMethod: '',
|
|
182
|
-
authUser: '',
|
|
183
|
-
},
|
|
184
|
-
authenticationResults: {
|
|
185
|
-
spf: 'none',
|
|
186
|
-
spfDomain: '',
|
|
187
|
-
dkim: 'none',
|
|
188
|
-
dkimDomain: '',
|
|
189
|
-
dmarc: 'none',
|
|
190
|
-
dmarcPolicy: '',
|
|
191
|
-
},
|
|
192
|
-
rejectionReason: item.status === 'failed' ? item.lastError : undefined,
|
|
193
|
-
bounceMessage: item.status === 'failed' ? item.lastError : undefined,
|
|
194
|
-
headers,
|
|
195
|
-
body,
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Map queue status to catalog TEmailStatus
|
|
200
|
-
*/
|
|
201
|
-
mapStatus(queueStatus) {
|
|
202
|
-
switch (queueStatus) {
|
|
203
|
-
case 'pending':
|
|
204
|
-
case 'processing':
|
|
205
|
-
return 'pending';
|
|
206
|
-
case 'delivered':
|
|
207
|
-
return 'delivered';
|
|
208
|
-
case 'failed':
|
|
209
|
-
return 'bounced';
|
|
210
|
-
case 'deferred':
|
|
211
|
-
return 'deferred';
|
|
212
|
-
default:
|
|
213
|
-
return 'pending';
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Format byte size to human-readable string
|
|
218
|
-
*/
|
|
219
|
-
formatSize(bytes) {
|
|
220
|
-
if (bytes < 1024)
|
|
221
|
-
return `${bytes} B`;
|
|
222
|
-
if (bytes < 1024 * 1024)
|
|
223
|
-
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
224
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1haWwtb3BzLmhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9vcHNzZXJ2ZXIvaGFuZGxlcnMvZW1haWwtb3BzLmhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUU1QyxPQUFPLEtBQUssVUFBVSxNQUFNLGlDQUFpQyxDQUFDO0FBRTlELE1BQU0sT0FBTyxlQUFlO0lBQ047SUFBcEIsWUFBb0IsWUFBdUI7UUFBdkIsaUJBQVksR0FBWixZQUFZLENBQVc7UUFDekMsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVPLGdCQUFnQjtRQUN0QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQztRQUNoRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQztRQUVsRCxpRkFBaUY7UUFFakYseUJBQXlCO1FBQ3pCLFVBQVUsQ0FBQyxlQUFlLENBQ3hCLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQ25DLGNBQWMsRUFDZCxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7WUFDaEIsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDeEMsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDO1FBQ3BCLENBQUMsQ0FDRixDQUNGLENBQUM7UUFFRiwyQkFBMkI7UUFDM0IsVUFBVSxDQUFDLGVBQWUsQ0FDeEIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDbkMsZ0JBQWdCLEVBQ2hCLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtZQUNoQixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNuRCxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDbkIsQ0FBQyxDQUNGLENBQ0YsQ0FBQztRQUVGLDBDQUEwQztRQUUxQyw4QkFBOEI7UUFDOUIsV0FBVyxDQUFDLGVBQWUsQ0FDekIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDbkMsYUFBYSxFQUNiLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtZQUNoQixNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUM7WUFDOUQsSUFBSSxDQUFDLFdBQVcsRUFBRSxhQUFhLEVBQUUsQ0FBQztnQkFDaEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLDRCQUE0QixFQUFFLENBQUM7WUFDakUsQ0FBQztZQUVELE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxhQUFhLENBQUM7WUFDeEMsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFNUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNWLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSwwQkFBMEIsRUFBRSxDQUFDO1lBQy9ELENBQUM7WUFFRCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQzdCLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSwwQ0FBMEMsSUFBSSxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUM7WUFDN0YsQ0FBQztZQUVELElBQUksQ0FBQztnQkFDSCxNQUFNLFVBQVUsR0FBRyxNQUFNLEtBQUssQ0FBQyxPQUFPLENBQ3BDLElBQUksQ0FBQyxnQkFBZ0IsRUFDckIsSUFBSSxDQUFDLGNBQWMsRUFDbkIsSUFBSSxDQUFDLEtBQUssQ0FDWCxDQUFDO2dCQUNGLE1BQU0sS0FBSyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ3hDLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxDQUFDO1lBQ3ZDLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLE9BQU87b0JBQ0wsT0FBTyxFQUFFLEtBQUs7b0JBQ2QsS0FBSyxFQUFFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLHdCQUF3QjtpQkFDekUsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDLENBQ0YsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0ssaUJBQWlCO1FBQ3ZCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLFdBQVcsQ0FBQztRQUM5RCxJQUFJLENBQUMsV0FBVyxFQUFFLGFBQWEsRUFBRSxDQUFDO1lBQ2hDLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztRQUVELE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxhQUFhLENBQUM7UUFDeEMsTUFBTSxRQUFRLEdBQUksS0FBYSxDQUFDLEtBQXlCLENBQUM7UUFFMUQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2QsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQWlDLEVBQUUsQ0FBQztRQUVoRCxLQUFLLE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLElBQUksUUFBUSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7WUFDNUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUM5QyxDQUFDO1FBRUQsOENBQThDO1FBQzlDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFFekYsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVEOztPQUVHO0lBQ0ssY0FBYyxDQUFDLE9BQWU7UUFDcEMsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDO1FBQzlELElBQUksQ0FBQyxXQUFXLEVBQUUsYUFBYSxFQUFFLENBQUM7WUFDaEMsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsTUFBTSxLQUFLLEdBQUcsV0FBVyxDQUFDLGFBQWEsQ0FBQztRQUN4QyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXBDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNWLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE9BQU8sSUFBSSxDQUFDLHlCQUF5QixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFRDs7T0FFRztJQUNLLG1CQUFtQixDQUFDLElBQVM7UUFDbkMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7UUFDL0MsSUFBSSxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ2QsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDO1FBQ1osSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2pCLElBQUksU0FBUyxHQUFHLEVBQUUsQ0FBQztRQUNuQixJQUFJLElBQUksR0FBRyxLQUFLLENBQUM7UUFFakIsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3JCLElBQUksZ0JBQWdCLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQzNCLElBQUksR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFDekMsRUFBRSxHQUFHLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ2hELE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQztZQUNqRCxDQUFDO2lCQUFNLElBQUksZ0JBQWdCLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ2pDLElBQUksR0FBRyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUM7Z0JBQzdCLEVBQUUsR0FBRyxDQUFDLGdCQUFnQixDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQzFDLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDO1lBQzNDLENBQUM7WUFFRCx1QkFBdUI7WUFDdkIsSUFBSSxPQUFPLGdCQUFnQixDQUFDLFlBQVksS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDeEQsSUFBSSxDQUFDO29CQUNILFNBQVMsR0FBRyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsSUFBSSxFQUFFLENBQUM7Z0JBQ3BELENBQUM7Z0JBQUMsTUFBTSxDQUFDO29CQUNQLFNBQVMsR0FBRyxFQUFFLENBQUM7Z0JBQ2pCLENBQUM7WUFDSCxDQUFDO1lBRUQsMkJBQTJCO1lBQzNCLE1BQU0sT0FBTyxHQUFHLGdCQUFnQixDQUFDLElBQUksRUFBRSxNQUFNLElBQUksQ0FBQyxDQUFDO1lBQ25ELE1BQU0sT0FBTyxHQUFHLGdCQUFnQixDQUFDLElBQUksRUFBRSxNQUFNLElBQUksQ0FBQyxDQUFDO1lBQ25ELElBQUksVUFBVSxHQUFHLENBQUMsQ0FBQztZQUNuQixJQUFJLE9BQU8sZ0JBQWdCLENBQUMsa0JBQWtCLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQzlELElBQUksQ0FBQztvQkFDSCxVQUFVLEdBQUcsZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQzFELENBQUM7Z0JBQUMsTUFBTSxDQUFDO29CQUNQLFVBQVUsR0FBRyxDQUFDLENBQUM7Z0JBQ2pCLENBQUM7WUFDSCxDQUFDO1lBQ0QsSUFBSSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxHQUFHLE9BQU8sR0FBRyxVQUFVLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBRUQsMkNBQTJDO1FBQzNDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTNDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLFlBQVksSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO1FBRTdGLE9BQU87WUFDTCxFQUFFLEVBQUUsSUFBSSxDQUFDLEVBQUU7WUFDWCxTQUFTLEVBQUUsVUFBaUQ7WUFDNUQsTUFBTTtZQUNOLElBQUk7WUFDSixFQUFFO1lBQ0YsT0FBTztZQUNQLFNBQVMsRUFBRSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxXQUFXLEVBQUU7WUFDNUMsU0FBUztZQUNULElBQUk7U0FDTCxDQUFDO0lBQ0osQ0FBQztJQUVEOztPQUVHO0lBQ0sseUJBQXlCLENBQUMsSUFBUztRQUN6QyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7UUFFL0MsSUFBSSxNQUFNLEdBQWEsRUFBRSxDQUFDO1FBQzFCLElBQUksRUFBRSxHQUFhLEVBQUUsQ0FBQztRQUN0QixJQUFJLE9BQU8sR0FBMkIsRUFBRSxDQUFDO1FBQ3pDLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUVkLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztZQUNyQixJQUFJLGdCQUFnQixDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUMzQixNQUFNLEdBQUcsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUM7Z0JBQ3pDLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQztZQUN2QyxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sTUFBTSxHQUFHLGdCQUFnQixDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUM7Z0JBQ25DLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDO1lBQ2pDLENBQUM7WUFFRCxPQUFPLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQztZQUN6QyxJQUFJLEdBQUcsZ0JBQWdCLENBQUMsSUFBSSxJQUFJLGdCQUFnQixDQUFDLElBQUksSUFBSSxFQUFFLENBQUM7UUFDOUQsQ0FBQztRQUVELE9BQU87WUFDTCxHQUFHLElBQUk7WUFDUCxNQUFNO1lBQ04sRUFBRTtZQUNGLE9BQU8sRUFBRSxFQUFFO1lBQ1gsY0FBYyxFQUFFO2dCQUNkLFFBQVEsRUFBRSxFQUFFO2dCQUNaLGNBQWMsRUFBRSxFQUFFO2dCQUNsQixhQUFhLEVBQUUsRUFBRTtnQkFDakIsZUFBZSxFQUFFLENBQUM7Z0JBQ2xCLFVBQVUsRUFBRSxFQUFFO2dCQUNkLFNBQVMsRUFBRSxFQUFFO2dCQUNiLGFBQWEsRUFBRSxLQUFLO2dCQUNwQixVQUFVLEVBQUUsRUFBRTtnQkFDZCxRQUFRLEVBQUUsRUFBRTthQUNiO1lBQ0QscUJBQXFCLEVBQUU7Z0JBQ3JCLEdBQUcsRUFBRSxNQUFNO2dCQUNYLFNBQVMsRUFBRSxFQUFFO2dCQUNiLElBQUksRUFBRSxNQUFNO2dCQUNaLFVBQVUsRUFBRSxFQUFFO2dCQUNkLEtBQUssRUFBRSxNQUFNO2dCQUNiLFdBQVcsRUFBRSxFQUFFO2FBQ2hCO1lBQ0QsZUFBZSxFQUFFLElBQUksQ0FBQyxNQUFNLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTO1lBQ3RFLGFBQWEsRUFBRSxJQUFJLENBQUMsTUFBTSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUztZQUNwRSxPQUFPO1lBQ1AsSUFBSTtTQUNMLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSyxTQUFTLENBQUMsV0FBbUI7UUFDbkMsUUFBUSxXQUFXLEVBQUUsQ0FBQztZQUNwQixLQUFLLFNBQVMsQ0FBQztZQUNmLEtBQUssWUFBWTtnQkFDZixPQUFPLFNBQVMsQ0FBQztZQUNuQixLQUFLLFdBQVc7Z0JBQ2QsT0FBTyxXQUFXLENBQUM7WUFDckIsS0FBSyxRQUFRO2dCQUNYLE9BQU8sU0FBUyxDQUFDO1lBQ25CLEtBQUssVUFBVTtnQkFDYixPQUFPLFVBQVUsQ0FBQztZQUNwQjtnQkFDRSxPQUFPLFNBQVMsQ0FBQztRQUNyQixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ssVUFBVSxDQUFDLEtBQWE7UUFDOUIsSUFBSSxLQUFLLEdBQUcsSUFBSTtZQUFFLE9BQU8sR0FBRyxLQUFLLElBQUksQ0FBQztRQUN0QyxJQUFJLEtBQUssR0FBRyxJQUFJLEdBQUcsSUFBSTtZQUFFLE9BQU8sR0FBRyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUNsRSxPQUFPLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztJQUNwRCxDQUFDO0NBQ0YifQ==
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export * from './admin.handler.js';
|
|
2
|
-
export * from './config.handler.js';
|
|
3
|
-
export * from './logs.handler.js';
|
|
4
|
-
export * from './security.handler.js';
|
|
5
|
-
export * from './stats.handler.js';
|
|
6
|
-
export * from './radius.handler.js';
|
|
7
|
-
export * from './email-ops.handler.js';
|
|
8
|
-
export * from './certificate.handler.js';
|
|
9
|
-
export * from './remoteingress.handler.js';
|
|
10
|
-
export * from './route-management.handler.js';
|
|
11
|
-
export * from './api-token.handler.js';
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export * from './admin.handler.js';
|
|
2
|
-
export * from './config.handler.js';
|
|
3
|
-
export * from './logs.handler.js';
|
|
4
|
-
export * from './security.handler.js';
|
|
5
|
-
export * from './stats.handler.js';
|
|
6
|
-
export * from './radius.handler.js';
|
|
7
|
-
export * from './email-ops.handler.js';
|
|
8
|
-
export * from './certificate.handler.js';
|
|
9
|
-
export * from './remoteingress.handler.js';
|
|
10
|
-
export * from './route-management.handler.js';
|
|
11
|
-
export * from './api-token.handler.js';
|
|
12
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9vcHNzZXJ2ZXIvaGFuZGxlcnMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYyxvQkFBb0IsQ0FBQztBQUNuQyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyx1QkFBdUIsQ0FBQztBQUN0QyxjQUFjLG9CQUFvQixDQUFDO0FBQ25DLGNBQWMscUJBQXFCLENBQUM7QUFDcEMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLDBCQUEwQixDQUFDO0FBQ3pDLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYywrQkFBK0IsQ0FBQztBQUM5QyxjQUFjLHdCQUF3QixDQUFDIn0=
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { OpsServer } from '../classes.opsserver.js';
|
|
2
|
-
export declare class LogsHandler {
|
|
3
|
-
private opsServerRef;
|
|
4
|
-
private activeStreamStops;
|
|
5
|
-
constructor(opsServerRef: OpsServer);
|
|
6
|
-
/**
|
|
7
|
-
* Clean up all active log streams and deactivate the push destination.
|
|
8
|
-
* Called when OpsServer stops.
|
|
9
|
-
*/
|
|
10
|
-
cleanup(): void;
|
|
11
|
-
private registerHandlers;
|
|
12
|
-
private static mapLogLevel;
|
|
13
|
-
private static deriveCategory;
|
|
14
|
-
private getRecentLogs;
|
|
15
|
-
/**
|
|
16
|
-
* Add a log destination to the base logger that pushes entries
|
|
17
|
-
* to all connected ops_dashboard TypedSocket clients.
|
|
18
|
-
*
|
|
19
|
-
* Uses a module-level singleton so the destination is added only once,
|
|
20
|
-
* even across OpsServer restart cycles. The destination reads
|
|
21
|
-
* `currentOpsServerRef` dynamically so it always uses the active server.
|
|
22
|
-
*/
|
|
23
|
-
private setupLogPushDestination;
|
|
24
|
-
private setupLogStream;
|
|
25
|
-
}
|
|
@@ -1,256 +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
|
-
// Module-level singleton: the log push destination is added once and reuses
|
|
5
|
-
// the current OpsServer reference so it survives OpsServer restarts without
|
|
6
|
-
// accumulating duplicate destinations.
|
|
7
|
-
let logPushDestinationInstalled = false;
|
|
8
|
-
let currentOpsServerRef = null;
|
|
9
|
-
export class LogsHandler {
|
|
10
|
-
opsServerRef;
|
|
11
|
-
activeStreamStops = new Set();
|
|
12
|
-
constructor(opsServerRef) {
|
|
13
|
-
this.opsServerRef = opsServerRef;
|
|
14
|
-
this.registerHandlers();
|
|
15
|
-
this.setupLogPushDestination();
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Clean up all active log streams and deactivate the push destination.
|
|
19
|
-
* Called when OpsServer stops.
|
|
20
|
-
*/
|
|
21
|
-
cleanup() {
|
|
22
|
-
// Stop all active follow-mode log streams
|
|
23
|
-
for (const stop of this.activeStreamStops) {
|
|
24
|
-
stop();
|
|
25
|
-
}
|
|
26
|
-
this.activeStreamStops.clear();
|
|
27
|
-
// Deactivate the push destination (it stays registered but becomes a no-op)
|
|
28
|
-
currentOpsServerRef = null;
|
|
29
|
-
}
|
|
30
|
-
registerHandlers() {
|
|
31
|
-
// All log endpoints register directly on viewRouter (valid identity required via middleware)
|
|
32
|
-
const router = this.opsServerRef.viewRouter;
|
|
33
|
-
// Get Recent Logs Handler
|
|
34
|
-
router.addTypedHandler(new plugins.typedrequest.TypedHandler('getRecentLogs', async (dataArg, toolsArg) => {
|
|
35
|
-
const logs = await this.getRecentLogs(dataArg.level, dataArg.category, dataArg.limit || 100, dataArg.offset || 0, dataArg.search, dataArg.timeRange);
|
|
36
|
-
return {
|
|
37
|
-
logs,
|
|
38
|
-
total: logs.length,
|
|
39
|
-
hasMore: false,
|
|
40
|
-
};
|
|
41
|
-
}));
|
|
42
|
-
// Get Log Stream Handler
|
|
43
|
-
router.addTypedHandler(new plugins.typedrequest.TypedHandler('getLogStream', async (dataArg, toolsArg) => {
|
|
44
|
-
// Create a virtual stream for log streaming
|
|
45
|
-
const virtualStream = new plugins.typedrequest.VirtualStream();
|
|
46
|
-
// Set up log streaming
|
|
47
|
-
const streamLogs = this.setupLogStream(virtualStream, dataArg.filters?.level, dataArg.filters?.category, dataArg.follow);
|
|
48
|
-
// Start streaming
|
|
49
|
-
streamLogs.start();
|
|
50
|
-
// Track the stop function so we can clean up on shutdown
|
|
51
|
-
this.activeStreamStops.add(streamLogs.stop);
|
|
52
|
-
return {
|
|
53
|
-
logStream: virtualStream,
|
|
54
|
-
};
|
|
55
|
-
}));
|
|
56
|
-
}
|
|
57
|
-
static mapLogLevel(smartlogLevel) {
|
|
58
|
-
switch (smartlogLevel) {
|
|
59
|
-
case 'silly':
|
|
60
|
-
case 'debug':
|
|
61
|
-
return 'debug';
|
|
62
|
-
case 'warn':
|
|
63
|
-
return 'warn';
|
|
64
|
-
case 'error':
|
|
65
|
-
return 'error';
|
|
66
|
-
default:
|
|
67
|
-
return 'info';
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
static deriveCategory(zone, message) {
|
|
71
|
-
const msg = (message || '').toLowerCase();
|
|
72
|
-
if (msg.includes('[security:') || msg.includes('security'))
|
|
73
|
-
return 'security';
|
|
74
|
-
if (zone === 'email' || msg.includes('email') || msg.includes('smtp') || msg.includes('mta'))
|
|
75
|
-
return 'email';
|
|
76
|
-
if (zone === 'dns' || msg.includes('dns'))
|
|
77
|
-
return 'dns';
|
|
78
|
-
if (msg.includes('smtp'))
|
|
79
|
-
return 'smtp';
|
|
80
|
-
return 'system';
|
|
81
|
-
}
|
|
82
|
-
async getRecentLogs(level, category, limit = 100, offset = 0, search, timeRange) {
|
|
83
|
-
// Compute a timestamp cutoff from timeRange
|
|
84
|
-
let since;
|
|
85
|
-
if (timeRange) {
|
|
86
|
-
const rangeMs = {
|
|
87
|
-
'1h': 3600000,
|
|
88
|
-
'6h': 21600000,
|
|
89
|
-
'24h': 86400000,
|
|
90
|
-
'7d': 604800000,
|
|
91
|
-
'30d': 2592000000,
|
|
92
|
-
};
|
|
93
|
-
since = Date.now() - (rangeMs[timeRange] || 86400000);
|
|
94
|
-
}
|
|
95
|
-
// Map the UI level to smartlog levels for filtering
|
|
96
|
-
const smartlogLevels = level
|
|
97
|
-
? level === 'debug'
|
|
98
|
-
? ['debug', 'silly']
|
|
99
|
-
: level === 'info'
|
|
100
|
-
? ['info', 'ok', 'success', 'note', 'lifecycle']
|
|
101
|
-
: [level]
|
|
102
|
-
: undefined;
|
|
103
|
-
// Fetch a larger batch from buffer, then apply category filter client-side
|
|
104
|
-
const rawEntries = logBuffer.getEntries({
|
|
105
|
-
level: smartlogLevels,
|
|
106
|
-
search,
|
|
107
|
-
since,
|
|
108
|
-
limit: limit * 3, // over-fetch to compensate for category filtering
|
|
109
|
-
offset: 0,
|
|
110
|
-
});
|
|
111
|
-
// Map ILogPackage → UI log format and apply category filter
|
|
112
|
-
const mapped = [];
|
|
113
|
-
for (const pkg of rawEntries) {
|
|
114
|
-
const uiLevel = LogsHandler.mapLogLevel(pkg.level);
|
|
115
|
-
const uiCategory = LogsHandler.deriveCategory(pkg.context?.zone, pkg.message);
|
|
116
|
-
if (category && uiCategory !== category)
|
|
117
|
-
continue;
|
|
118
|
-
mapped.push({
|
|
119
|
-
timestamp: pkg.timestamp,
|
|
120
|
-
level: uiLevel,
|
|
121
|
-
category: uiCategory,
|
|
122
|
-
message: pkg.message,
|
|
123
|
-
metadata: pkg.data,
|
|
124
|
-
});
|
|
125
|
-
if (mapped.length >= limit)
|
|
126
|
-
break;
|
|
127
|
-
}
|
|
128
|
-
return mapped;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Add a log destination to the base logger that pushes entries
|
|
132
|
-
* to all connected ops_dashboard TypedSocket clients.
|
|
133
|
-
*
|
|
134
|
-
* Uses a module-level singleton so the destination is added only once,
|
|
135
|
-
* even across OpsServer restart cycles. The destination reads
|
|
136
|
-
* `currentOpsServerRef` dynamically so it always uses the active server.
|
|
137
|
-
*/
|
|
138
|
-
setupLogPushDestination() {
|
|
139
|
-
// Update the module-level reference so the existing destination uses the new server
|
|
140
|
-
currentOpsServerRef = this.opsServerRef;
|
|
141
|
-
if (logPushDestinationInstalled) {
|
|
142
|
-
return; // destination already registered — just updated the ref
|
|
143
|
-
}
|
|
144
|
-
logPushDestinationInstalled = true;
|
|
145
|
-
baseLogger.addLogDestination({
|
|
146
|
-
async handleLog(logPackage) {
|
|
147
|
-
const opsServer = currentOpsServerRef;
|
|
148
|
-
if (!opsServer)
|
|
149
|
-
return;
|
|
150
|
-
const typedsocket = opsServer.server?.typedserver?.typedsocket;
|
|
151
|
-
if (!typedsocket)
|
|
152
|
-
return;
|
|
153
|
-
let connections;
|
|
154
|
-
try {
|
|
155
|
-
connections = await typedsocket.findAllTargetConnectionsByTag('role', 'ops_dashboard');
|
|
156
|
-
}
|
|
157
|
-
catch {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
if (connections.length === 0)
|
|
161
|
-
return;
|
|
162
|
-
const entry = {
|
|
163
|
-
timestamp: logPackage.timestamp || Date.now(),
|
|
164
|
-
level: LogsHandler.mapLogLevel(logPackage.level),
|
|
165
|
-
category: LogsHandler.deriveCategory(logPackage.context?.zone, logPackage.message),
|
|
166
|
-
message: logPackage.message,
|
|
167
|
-
metadata: logPackage.data,
|
|
168
|
-
};
|
|
169
|
-
for (const conn of connections) {
|
|
170
|
-
try {
|
|
171
|
-
const push = typedsocket.createTypedRequest('pushLogEntry', conn);
|
|
172
|
-
push.fire({ entry }).catch(() => { }); // fire-and-forget
|
|
173
|
-
}
|
|
174
|
-
catch {
|
|
175
|
-
// connection may have closed
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
setupLogStream(virtualStream, levelFilter, categoryFilter, follow = true) {
|
|
182
|
-
let intervalId = null;
|
|
183
|
-
let stopped = false;
|
|
184
|
-
let logIndex = 0;
|
|
185
|
-
const stop = () => {
|
|
186
|
-
stopped = true;
|
|
187
|
-
if (intervalId) {
|
|
188
|
-
clearInterval(intervalId);
|
|
189
|
-
intervalId = null;
|
|
190
|
-
}
|
|
191
|
-
this.activeStreamStops.delete(stop);
|
|
192
|
-
};
|
|
193
|
-
const start = () => {
|
|
194
|
-
if (!follow) {
|
|
195
|
-
// Send existing logs and close
|
|
196
|
-
this.getRecentLogs(levelFilter?.[0], categoryFilter?.[0], 100, 0).then(logs => {
|
|
197
|
-
logs.forEach(log => {
|
|
198
|
-
const logData = JSON.stringify(log);
|
|
199
|
-
const encoder = new TextEncoder();
|
|
200
|
-
virtualStream.sendData(encoder.encode(logData));
|
|
201
|
-
});
|
|
202
|
-
});
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
// For follow mode, simulate real-time log streaming
|
|
206
|
-
intervalId = setInterval(async () => {
|
|
207
|
-
if (stopped) {
|
|
208
|
-
// Guard: clear interval if stop() was called between ticks
|
|
209
|
-
clearInterval(intervalId);
|
|
210
|
-
intervalId = null;
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
const categories = ['smtp', 'dns', 'security', 'system', 'email'];
|
|
214
|
-
const levels = ['info', 'warn', 'error', 'debug'];
|
|
215
|
-
const mockCategory = categories[Math.floor(Math.random() * categories.length)];
|
|
216
|
-
const mockLevel = levels[Math.floor(Math.random() * levels.length)];
|
|
217
|
-
// Filter by requested criteria
|
|
218
|
-
if (levelFilter && !levelFilter.includes(mockLevel))
|
|
219
|
-
return;
|
|
220
|
-
if (categoryFilter && !categoryFilter.includes(mockCategory))
|
|
221
|
-
return;
|
|
222
|
-
const logEntry = {
|
|
223
|
-
timestamp: Date.now(),
|
|
224
|
-
level: mockLevel,
|
|
225
|
-
category: mockCategory,
|
|
226
|
-
message: `Real-time log ${logIndex++} from ${mockCategory}`,
|
|
227
|
-
metadata: {
|
|
228
|
-
requestId: plugins.uuid.v4(),
|
|
229
|
-
},
|
|
230
|
-
};
|
|
231
|
-
const logData = JSON.stringify(logEntry);
|
|
232
|
-
const encoder = new TextEncoder();
|
|
233
|
-
try {
|
|
234
|
-
// Use a timeout to detect hung streams (sendData can hang if the
|
|
235
|
-
// VirtualStream's keepAlive loop has ended)
|
|
236
|
-
let timeoutHandle;
|
|
237
|
-
await Promise.race([
|
|
238
|
-
virtualStream.sendData(encoder.encode(logData)).then((result) => {
|
|
239
|
-
clearTimeout(timeoutHandle);
|
|
240
|
-
return result;
|
|
241
|
-
}),
|
|
242
|
-
new Promise((_, reject) => {
|
|
243
|
-
timeoutHandle = setTimeout(() => reject(new Error('stream send timeout')), 10_000);
|
|
244
|
-
}),
|
|
245
|
-
]);
|
|
246
|
-
}
|
|
247
|
-
catch {
|
|
248
|
-
// Stream closed, errored, or timed out — clean up
|
|
249
|
-
stop();
|
|
250
|
-
}
|
|
251
|
-
}, 2000);
|
|
252
|
-
};
|
|
253
|
-
return { start, stop };
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9ncy5oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvb3Bzc2VydmVyL2hhbmRsZXJzL2xvZ3MuaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBRTVDLE9BQU8sS0FBSyxVQUFVLE1BQU0saUNBQWlDLENBQUM7QUFDOUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV4RCw0RUFBNEU7QUFDNUUsNEVBQTRFO0FBQzVFLHVDQUF1QztBQUN2QyxJQUFJLDJCQUEyQixHQUFHLEtBQUssQ0FBQztBQUN4QyxJQUFJLG1CQUFtQixHQUFxQixJQUFJLENBQUM7QUFFakQsTUFBTSxPQUFPLFdBQVc7SUFHRjtJQUZaLGlCQUFpQixHQUFvQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRXZELFlBQW9CLFlBQXVCO1FBQXZCLGlCQUFZLEdBQVosWUFBWSxDQUFXO1FBQ3pDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO0lBQ2pDLENBQUM7SUFFRDs7O09BR0c7SUFDSSxPQUFPO1FBQ1osMENBQTBDO1FBQzFDLEtBQUssTUFBTSxJQUFJLElBQUksSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDMUMsSUFBSSxFQUFFLENBQUM7UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxDQUFDO1FBQy9CLDRFQUE0RTtRQUM1RSxtQkFBbUIsR0FBRyxJQUFJLENBQUM7SUFDN0IsQ0FBQztJQUVPLGdCQUFnQjtRQUN0Qiw2RkFBNkY7UUFDN0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUM7UUFFNUMsMEJBQTBCO1FBQzFCLE1BQU0sQ0FBQyxlQUFlLENBQ3BCLElBQUksT0FBTyxD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
|