@serve.zone/dcrouter 11.0.40 → 11.0.45
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/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/cache/classes.cache.cleaner.d.ts +47 -0
- package/dist_ts/cache/classes.cache.cleaner.js +130 -0
- package/dist_ts/cache/classes.cached.document.d.ts +76 -0
- package/dist_ts/cache/classes.cached.document.js +100 -0
- package/dist_ts/cache/classes.cachedb.d.ts +60 -0
- package/dist_ts/cache/classes.cachedb.js +126 -0
- package/dist_ts/cache/documents/classes.cached.email.d.ts +125 -0
- package/dist_ts/cache/documents/classes.cached.email.js +337 -0
- package/dist_ts/cache/documents/classes.cached.ip.reputation.d.ts +119 -0
- package/dist_ts/cache/documents/classes.cached.ip.reputation.js +323 -0
- package/dist_ts/cache/documents/index.d.ts +2 -0
- package/dist_ts/cache/documents/index.js +3 -0
- package/dist_ts/cache/index.d.ts +4 -0
- package/dist_ts/cache/index.js +7 -0
- package/dist_ts/classes.cert-provision-scheduler.d.ts +53 -0
- package/dist_ts/classes.cert-provision-scheduler.js +110 -0
- package/dist_ts/classes.storage-cert-manager.d.ts +18 -0
- package/dist_ts/classes.storage-cert-manager.js +43 -0
- package/dist_ts/logger.d.ts +21 -0
- package/dist_ts/logger.js +81 -0
- package/dist_ts/monitoring/classes.metricscache.d.ts +32 -0
- package/dist_ts/monitoring/classes.metricscache.js +63 -0
- package/dist_ts/opsserver/handlers/admin.handler.d.ts +31 -0
- package/dist_ts/opsserver/handlers/admin.handler.js +180 -0
- package/dist_ts/opsserver/handlers/config.handler.d.ts +7 -0
- package/dist_ts/opsserver/handlers/config.handler.js +192 -0
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +25 -0
- package/dist_ts/opsserver/handlers/logs.handler.js +256 -0
- package/dist_ts/paths.d.ts +26 -0
- package/dist_ts/paths.js +45 -0
- package/dist_ts/plugins.d.ts +79 -0
- package/dist_ts/plugins.js +113 -0
- package/dist_ts/security/classes.securitylogger.d.ts +144 -0
- package/dist_ts/security/classes.securitylogger.js +233 -0
- package/dist_ts/storage/classes.storagemanager.d.ts +83 -0
- package/dist_ts/storage/classes.storagemanager.js +350 -0
- package/dist_ts/storage/index.d.ts +1 -0
- package/dist_ts/storage/index.js +3 -0
- 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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import { SmartlogDestinationBuffer } from '@push.rocks/smartlog/destination-buffer';
|
|
4
|
+
// Map NODE_ENV to valid TEnvironment
|
|
5
|
+
const nodeEnv = process.env.NODE_ENV || 'production';
|
|
6
|
+
const envMap = {
|
|
7
|
+
'development': 'local',
|
|
8
|
+
'test': 'test',
|
|
9
|
+
'staging': 'staging',
|
|
10
|
+
'production': 'production'
|
|
11
|
+
};
|
|
12
|
+
// In-memory log buffer for the OpsServer UI
|
|
13
|
+
export const logBuffer = new SmartlogDestinationBuffer({ maxEntries: 2000 });
|
|
14
|
+
// Default Smartlog instance (exported so OpsServer can add push destinations)
|
|
15
|
+
export const baseLogger = new plugins.smartlog.Smartlog({
|
|
16
|
+
logContext: {
|
|
17
|
+
environment: envMap[nodeEnv] || 'production',
|
|
18
|
+
runtime: 'node',
|
|
19
|
+
zone: 'serve.zone',
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
// Wire the buffer destination so all logs are captured
|
|
23
|
+
baseLogger.addLogDestination(logBuffer);
|
|
24
|
+
// Extended logger compatible with the original enhanced logger API
|
|
25
|
+
class StandardLogger {
|
|
26
|
+
defaultContext = {};
|
|
27
|
+
correlationId = null;
|
|
28
|
+
constructor() { }
|
|
29
|
+
// Log methods
|
|
30
|
+
log(level, message, context = {}) {
|
|
31
|
+
const combinedContext = {
|
|
32
|
+
...this.defaultContext,
|
|
33
|
+
...context
|
|
34
|
+
};
|
|
35
|
+
if (this.correlationId) {
|
|
36
|
+
combinedContext.correlation_id = this.correlationId;
|
|
37
|
+
}
|
|
38
|
+
baseLogger.log(level, message, combinedContext);
|
|
39
|
+
}
|
|
40
|
+
error(message, context = {}) {
|
|
41
|
+
this.log('error', message, context);
|
|
42
|
+
}
|
|
43
|
+
warn(message, context = {}) {
|
|
44
|
+
this.log('warn', message, context);
|
|
45
|
+
}
|
|
46
|
+
info(message, context = {}) {
|
|
47
|
+
this.log('info', message, context);
|
|
48
|
+
}
|
|
49
|
+
success(message, context = {}) {
|
|
50
|
+
this.log('success', message, context);
|
|
51
|
+
}
|
|
52
|
+
debug(message, context = {}) {
|
|
53
|
+
this.log('debug', message, context);
|
|
54
|
+
}
|
|
55
|
+
// Context management
|
|
56
|
+
setContext(context, overwrite = false) {
|
|
57
|
+
if (overwrite) {
|
|
58
|
+
this.defaultContext = context;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
this.defaultContext = {
|
|
62
|
+
...this.defaultContext,
|
|
63
|
+
...context
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Correlation ID management
|
|
68
|
+
setCorrelationId(id = null) {
|
|
69
|
+
this.correlationId = id || randomUUID();
|
|
70
|
+
return this.correlationId;
|
|
71
|
+
}
|
|
72
|
+
getCorrelationId() {
|
|
73
|
+
return this.correlationId;
|
|
74
|
+
}
|
|
75
|
+
clearCorrelationId() {
|
|
76
|
+
this.correlationId = null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// Export a singleton instance
|
|
80
|
+
export const logger = new StandardLogger();
|
|
81
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvbG9nZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDekMsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFFcEYscUNBQXFDO0FBQ3JDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxJQUFJLFlBQVksQ0FBQztBQUNyRCxNQUFNLE1BQU0sR0FBZ0U7SUFDMUUsYUFBYSxFQUFFLE9BQU87SUFDdEIsTUFBTSxFQUFFLE1BQU07SUFDZCxTQUFTLEVBQUUsU0FBUztJQUNwQixZQUFZLEVBQUUsWUFBWTtDQUMzQixDQUFDO0FBRUYsNENBQTRDO0FBQzVDLE1BQU0sQ0FBQyxNQUFNLFNBQVMsR0FBRyxJQUFJLHlCQUF5QixDQUFDLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFFN0UsOEVBQThFO0FBQzlFLE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDO0lBQ3RELFVBQVUsRUFBRTtRQUNWLFdBQVcsRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksWUFBWTtRQUM1QyxPQUFPLEVBQUUsTUFBTTtRQUNmLElBQUksRUFBRSxZQUFZO0tBQ25CO0NBQ0YsQ0FBQyxDQUFDO0FBRUgsdURBQXVEO0FBQ3ZELFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUV4QyxtRUFBbUU7QUFDbkUsTUFBTSxjQUFjO0lBQ1YsY0FBYyxHQUF3QixFQUFFLENBQUM7SUFDekMsYUFBYSxHQUFrQixJQUFJLENBQUM7SUFFNUMsZ0JBQWUsQ0FBQztJQUVoQixjQUFjO0lBQ1AsR0FBRyxDQUFDLEtBQXNELEVBQUUsT0FBZSxFQUFFLFVBQStCLEVBQUU7UUFDbkgsTUFBTSxlQUFlLEdBQUc7WUFDdEIsR0FBRyxJQUFJLENBQUMsY0FBYztZQUN0QixHQUFHLE9BQU87U0FDWCxDQUFDO1FBRUYsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdkIsZUFBZSxDQUFDLGNBQWMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO1FBQ3RELENBQUM7UUFFRCxVQUFVLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVNLEtBQUssQ0FBQyxPQUFlLEVBQUUsVUFBK0IsRUFBRTtRQUM3RCxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVNLElBQUksQ0FBQyxPQUFlLEVBQUUsVUFBK0IsRUFBRTtRQUM1RCxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVNLElBQUksQ0FBQyxPQUFlLEVBQUUsVUFBK0IsRUFBRTtRQUM1RCxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVNLE9BQU8sQ0FBQyxPQUFlLEVBQUUsVUFBK0IsRUFBRTtRQUMvRCxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVNLEtBQUssQ0FBQyxPQUFlLEVBQUUsVUFBK0IsRUFBRTtRQUM3RCxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELHFCQUFxQjtJQUNkLFVBQVUsQ0FBQyxPQUE0QixFQUFFLFlBQXFCLEtBQUs7UUFDeEUsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNkLElBQUksQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDO1FBQ2hDLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLGNBQWMsR0FBRztnQkFDcEIsR0FBRyxJQUFJLENBQUMsY0FBYztnQkFDdEIsR0FBRyxPQUFPO2FBQ1gsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQsNEJBQTRCO0lBQ3JCLGdCQUFnQixDQUFDLEtBQW9CLElBQUk7UUFDOUMsSUFBSSxDQUFDLGFBQWEsR0FBRyxFQUFFLElBQUksVUFBVSxFQUFFLENBQUM7UUFDeEMsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQzVCLENBQUM7SUFFTSxnQkFBZ0I7UUFDckIsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQzVCLENBQUM7SUFFTSxrQkFBa0I7UUFDdkIsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBRUQsOEJBQThCO0FBQzlCLE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxJQUFJLGNBQWMsRUFBRSxDQUFDIn0=
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface ICacheEntry<T> {
|
|
2
|
+
data: T;
|
|
3
|
+
timestamp: number;
|
|
4
|
+
}
|
|
5
|
+
export declare class MetricsCache {
|
|
6
|
+
private cache;
|
|
7
|
+
private readonly defaultTTL;
|
|
8
|
+
constructor(defaultTTL?: number);
|
|
9
|
+
/**
|
|
10
|
+
* Get cached data or compute and cache it
|
|
11
|
+
*/
|
|
12
|
+
get<T>(key: string, computeFn: () => T | Promise<T>, ttl?: number): T | Promise<T>;
|
|
13
|
+
/**
|
|
14
|
+
* Invalidate a specific cache entry
|
|
15
|
+
*/
|
|
16
|
+
invalidate(key: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Clear all cache entries
|
|
19
|
+
*/
|
|
20
|
+
clear(): void;
|
|
21
|
+
/**
|
|
22
|
+
* Get cache statistics
|
|
23
|
+
*/
|
|
24
|
+
getStats(): {
|
|
25
|
+
size: number;
|
|
26
|
+
keys: string[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Clean up expired entries
|
|
30
|
+
*/
|
|
31
|
+
cleanup(): void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export class MetricsCache {
|
|
2
|
+
cache = new Map();
|
|
3
|
+
defaultTTL;
|
|
4
|
+
constructor(defaultTTL = 500) {
|
|
5
|
+
this.defaultTTL = defaultTTL;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Get cached data or compute and cache it
|
|
9
|
+
*/
|
|
10
|
+
get(key, computeFn, ttl) {
|
|
11
|
+
const cached = this.cache.get(key);
|
|
12
|
+
const now = Date.now();
|
|
13
|
+
const actualTTL = ttl ?? this.defaultTTL;
|
|
14
|
+
if (cached && (now - cached.timestamp) < actualTTL) {
|
|
15
|
+
return cached.data;
|
|
16
|
+
}
|
|
17
|
+
const result = computeFn();
|
|
18
|
+
// Handle both sync and async compute functions
|
|
19
|
+
if (result instanceof Promise) {
|
|
20
|
+
return result.then(data => {
|
|
21
|
+
this.cache.set(key, { data, timestamp: now });
|
|
22
|
+
return data;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
this.cache.set(key, { data: result, timestamp: now });
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Invalidate a specific cache entry
|
|
32
|
+
*/
|
|
33
|
+
invalidate(key) {
|
|
34
|
+
this.cache.delete(key);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Clear all cache entries
|
|
38
|
+
*/
|
|
39
|
+
clear() {
|
|
40
|
+
this.cache.clear();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get cache statistics
|
|
44
|
+
*/
|
|
45
|
+
getStats() {
|
|
46
|
+
return {
|
|
47
|
+
size: this.cache.size,
|
|
48
|
+
keys: Array.from(this.cache.keys())
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Clean up expired entries
|
|
53
|
+
*/
|
|
54
|
+
cleanup() {
|
|
55
|
+
const now = Date.now();
|
|
56
|
+
for (const [key, entry] of this.cache.entries()) {
|
|
57
|
+
if (now - entry.timestamp > this.defaultTTL) {
|
|
58
|
+
this.cache.delete(key);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5tZXRyaWNzY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9tb25pdG9yaW5nL2NsYXNzZXMubWV0cmljc2NhY2hlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUtBLE1BQU0sT0FBTyxZQUFZO0lBQ2YsS0FBSyxHQUFHLElBQUksR0FBRyxFQUE0QixDQUFDO0lBQ25DLFVBQVUsQ0FBUztJQUVwQyxZQUFZLGFBQXFCLEdBQUc7UUFDbEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7SUFDL0IsQ0FBQztJQUVEOztPQUVHO0lBQ0ksR0FBRyxDQUFJLEdBQVcsRUFBRSxTQUErQixFQUFFLEdBQVk7UUFDdEUsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3ZCLE1BQU0sU0FBUyxHQUFHLEdBQUcsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDO1FBRXpDLElBQUksTUFBTSxJQUFJLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxTQUFTLEVBQUUsQ0FBQztZQUNuRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUM7UUFDckIsQ0FBQztRQUVELE1BQU0sTUFBTSxHQUFHLFNBQVMsRUFBRSxDQUFDO1FBRTNCLCtDQUErQztRQUMvQyxJQUFJLE1BQU0sWUFBWSxPQUFPLEVBQUUsQ0FBQztZQUM5QixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ3hCLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztnQkFDOUMsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUN0RCxPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksVUFBVSxDQUFDLEdBQVc7UUFDM0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSztRQUNWLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDckIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksUUFBUTtRQUNiLE9BQU87WUFDTCxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJO1lBQ3JCLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDcEMsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNJLE9BQU87UUFDWixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDdkIsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztZQUNoRCxJQUFJLEdBQUcsR0FBRyxLQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDNUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDekIsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
4
|
+
export interface IJwtData {
|
|
5
|
+
userId: string;
|
|
6
|
+
status: 'loggedIn' | 'loggedOut';
|
|
7
|
+
expiresAt: number;
|
|
8
|
+
}
|
|
9
|
+
export declare class AdminHandler {
|
|
10
|
+
private opsServerRef;
|
|
11
|
+
typedrouter: plugins.typedrequest.TypedRouter<interfaces.typedrequestInterfaces.ITypedRequest>;
|
|
12
|
+
smartjwtInstance: plugins.smartjwt.SmartJwt<IJwtData>;
|
|
13
|
+
private users;
|
|
14
|
+
constructor(opsServerRef: OpsServer);
|
|
15
|
+
initialize(): Promise<void>;
|
|
16
|
+
private initializeJwt;
|
|
17
|
+
private initializeDefaultUsers;
|
|
18
|
+
private registerHandlers;
|
|
19
|
+
/**
|
|
20
|
+
* Create a guard for valid identity (matching cloudly pattern)
|
|
21
|
+
*/
|
|
22
|
+
validIdentityGuard: plugins.smartguard.Guard<{
|
|
23
|
+
identity: interfaces.data.IIdentity;
|
|
24
|
+
}>;
|
|
25
|
+
/**
|
|
26
|
+
* Create a guard for admin identity (matching cloudly pattern)
|
|
27
|
+
*/
|
|
28
|
+
adminIdentityGuard: plugins.smartguard.Guard<{
|
|
29
|
+
identity: interfaces.data.IIdentity;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
3
|
+
export class AdminHandler {
|
|
4
|
+
opsServerRef;
|
|
5
|
+
typedrouter = new plugins.typedrequest.TypedRouter();
|
|
6
|
+
// JWT instance
|
|
7
|
+
smartjwtInstance;
|
|
8
|
+
// Simple in-memory user storage (in production, use proper database)
|
|
9
|
+
users = new Map();
|
|
10
|
+
constructor(opsServerRef) {
|
|
11
|
+
this.opsServerRef = opsServerRef;
|
|
12
|
+
// Add this handler's router to the parent
|
|
13
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
14
|
+
}
|
|
15
|
+
async initialize() {
|
|
16
|
+
await this.initializeJwt();
|
|
17
|
+
this.initializeDefaultUsers();
|
|
18
|
+
this.registerHandlers();
|
|
19
|
+
}
|
|
20
|
+
async initializeJwt() {
|
|
21
|
+
this.smartjwtInstance = new plugins.smartjwt.SmartJwt();
|
|
22
|
+
await this.smartjwtInstance.init();
|
|
23
|
+
// For development, create new keypair each time
|
|
24
|
+
// In production, load from storage like cloudly does
|
|
25
|
+
await this.smartjwtInstance.createNewKeyPair();
|
|
26
|
+
}
|
|
27
|
+
initializeDefaultUsers() {
|
|
28
|
+
// Add default admin user
|
|
29
|
+
const adminId = plugins.uuid.v4();
|
|
30
|
+
this.users.set(adminId, {
|
|
31
|
+
id: adminId,
|
|
32
|
+
username: 'admin',
|
|
33
|
+
password: 'admin',
|
|
34
|
+
role: 'admin',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
registerHandlers() {
|
|
38
|
+
// Admin Login Handler
|
|
39
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('adminLoginWithUsernameAndPassword', async (dataArg) => {
|
|
40
|
+
try {
|
|
41
|
+
// Find user by username and password
|
|
42
|
+
let user = null;
|
|
43
|
+
for (const [_, userData] of this.users) {
|
|
44
|
+
if (userData.username === dataArg.username && userData.password === dataArg.password) {
|
|
45
|
+
user = userData;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (!user) {
|
|
50
|
+
throw new plugins.typedrequest.TypedResponseError('login failed');
|
|
51
|
+
}
|
|
52
|
+
const expiresAtTimestamp = Date.now() + 3600 * 1000 * 24; // 24 hours
|
|
53
|
+
const jwt = await this.smartjwtInstance.createJWT({
|
|
54
|
+
userId: user.id,
|
|
55
|
+
status: 'loggedIn',
|
|
56
|
+
expiresAt: expiresAtTimestamp,
|
|
57
|
+
});
|
|
58
|
+
return {
|
|
59
|
+
identity: {
|
|
60
|
+
jwt,
|
|
61
|
+
userId: user.id,
|
|
62
|
+
name: user.username,
|
|
63
|
+
expiresAt: expiresAtTimestamp,
|
|
64
|
+
role: user.role,
|
|
65
|
+
type: 'user',
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (error instanceof plugins.typedrequest.TypedResponseError) {
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
throw new plugins.typedrequest.TypedResponseError('login failed');
|
|
74
|
+
}
|
|
75
|
+
}));
|
|
76
|
+
// Admin Logout Handler
|
|
77
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('adminLogout', async (dataArg) => {
|
|
78
|
+
// In a real implementation, you might want to blacklist the JWT
|
|
79
|
+
// For now, just return success
|
|
80
|
+
return {
|
|
81
|
+
success: true,
|
|
82
|
+
};
|
|
83
|
+
}));
|
|
84
|
+
// Verify Identity Handler
|
|
85
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('verifyIdentity', async (dataArg) => {
|
|
86
|
+
if (!dataArg.identity?.jwt) {
|
|
87
|
+
return {
|
|
88
|
+
valid: false,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
try {
|
|
92
|
+
const jwtData = await this.smartjwtInstance.verifyJWTAndGetData(dataArg.identity.jwt);
|
|
93
|
+
// Check if expired
|
|
94
|
+
if (jwtData.expiresAt < Date.now()) {
|
|
95
|
+
return {
|
|
96
|
+
valid: false,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// Check if logged in
|
|
100
|
+
if (jwtData.status !== 'loggedIn') {
|
|
101
|
+
return {
|
|
102
|
+
valid: false,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// Find user
|
|
106
|
+
const user = this.users.get(jwtData.userId);
|
|
107
|
+
if (!user) {
|
|
108
|
+
return {
|
|
109
|
+
valid: false,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
valid: true,
|
|
114
|
+
identity: {
|
|
115
|
+
jwt: dataArg.identity.jwt,
|
|
116
|
+
userId: user.id,
|
|
117
|
+
name: user.username,
|
|
118
|
+
expiresAt: jwtData.expiresAt,
|
|
119
|
+
role: user.role,
|
|
120
|
+
type: 'user',
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
return {
|
|
126
|
+
valid: false,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}));
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Create a guard for valid identity (matching cloudly pattern)
|
|
133
|
+
*/
|
|
134
|
+
validIdentityGuard = new plugins.smartguard.Guard(async (dataArg) => {
|
|
135
|
+
if (!dataArg.identity?.jwt) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
const jwtData = await this.smartjwtInstance.verifyJWTAndGetData(dataArg.identity.jwt);
|
|
140
|
+
// Check expiration
|
|
141
|
+
if (jwtData.expiresAt < Date.now()) {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
// Check status
|
|
145
|
+
if (jwtData.status !== 'loggedIn') {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
// Verify data hasn't been tampered with
|
|
149
|
+
if (dataArg.identity.expiresAt !== jwtData.expiresAt) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
if (dataArg.identity.userId !== jwtData.userId) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
}, {
|
|
161
|
+
failedHint: 'identity is not valid',
|
|
162
|
+
name: 'validIdentityGuard',
|
|
163
|
+
});
|
|
164
|
+
/**
|
|
165
|
+
* Create a guard for admin identity (matching cloudly pattern)
|
|
166
|
+
*/
|
|
167
|
+
adminIdentityGuard = new plugins.smartguard.Guard(async (dataArg) => {
|
|
168
|
+
// First check if identity is valid
|
|
169
|
+
const isValid = await this.validIdentityGuard.exec(dataArg);
|
|
170
|
+
if (!isValid) {
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
// Check if user has admin role
|
|
174
|
+
return dataArg.identity.role === 'admin';
|
|
175
|
+
}, {
|
|
176
|
+
failedHint: 'user is not admin',
|
|
177
|
+
name: 'adminIdentityGuard',
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRtaW4uaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL29wc3NlcnZlci9oYW5kbGVycy9hZG1pbi5oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFFNUMsT0FBTyxLQUFLLFVBQVUsTUFBTSxpQ0FBaUMsQ0FBQztBQVE5RCxNQUFNLE9BQU8sWUFBWTtJQWNIO0lBYmIsV0FBVyxHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUU1RCxlQUFlO0lBQ1IsZ0JBQWdCLENBQXNDO0lBRTdELHFFQUFxRTtJQUM3RCxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBS25CLENBQUM7SUFFTCxZQUFvQixZQUF1QjtRQUF2QixpQkFBWSxHQUFaLFlBQVksQ0FBVztRQUN6QywwQ0FBMEM7UUFDMUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBRU0sS0FBSyxDQUFDLFVBQVU7UUFDckIsTUFBTSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDM0IsSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFDOUIsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVPLEtBQUssQ0FBQyxhQUFhO1FBQ3pCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDeEQsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLENBQUM7UUFFbkMsZ0RBQWdEO1FBQ2hELHFEQUFxRDtRQUNyRCxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO0lBQ2pELENBQUM7SUFFTyxzQkFBc0I7UUFDNUIseUJBQXlCO1FB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
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as paths from '../../paths.js';
|
|
3
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
4
|
+
export class ConfigHandler {
|
|
5
|
+
opsServerRef;
|
|
6
|
+
constructor(opsServerRef) {
|
|
7
|
+
this.opsServerRef = opsServerRef;
|
|
8
|
+
this.registerHandlers();
|
|
9
|
+
}
|
|
10
|
+
registerHandlers() {
|
|
11
|
+
// Config endpoint registers directly on viewRouter (valid identity required via middleware)
|
|
12
|
+
const router = this.opsServerRef.viewRouter;
|
|
13
|
+
// Get Configuration Handler (read-only)
|
|
14
|
+
router.addTypedHandler(new plugins.typedrequest.TypedHandler('getConfiguration', async (dataArg, toolsArg) => {
|
|
15
|
+
const config = await this.getConfiguration();
|
|
16
|
+
return {
|
|
17
|
+
config,
|
|
18
|
+
section: dataArg.section,
|
|
19
|
+
};
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
async getConfiguration() {
|
|
23
|
+
const dcRouter = this.opsServerRef.dcRouterRef;
|
|
24
|
+
const opts = dcRouter.options;
|
|
25
|
+
const resolvedPaths = dcRouter.resolvedPaths;
|
|
26
|
+
// --- System ---
|
|
27
|
+
const storageBackend = opts.storage?.readFunction
|
|
28
|
+
? 'custom'
|
|
29
|
+
: opts.storage?.fsPath
|
|
30
|
+
? 'filesystem'
|
|
31
|
+
: 'memory';
|
|
32
|
+
// Resolve proxy IPs: fall back to SmartProxy's runtime proxyIPs if not in opts
|
|
33
|
+
let proxyIps = opts.proxyIps || [];
|
|
34
|
+
if (proxyIps.length === 0 && dcRouter.smartProxy) {
|
|
35
|
+
const spSettings = dcRouter.smartProxy.settings;
|
|
36
|
+
if (spSettings?.proxyIPs?.length > 0) {
|
|
37
|
+
proxyIps = spSettings.proxyIPs;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const system = {
|
|
41
|
+
baseDir: resolvedPaths.dcrouterHomeDir,
|
|
42
|
+
dataDir: resolvedPaths.dataDir,
|
|
43
|
+
publicIp: opts.publicIp || dcRouter.detectedPublicIp || null,
|
|
44
|
+
proxyIps,
|
|
45
|
+
uptime: Math.floor(process.uptime()),
|
|
46
|
+
storageBackend,
|
|
47
|
+
storagePath: opts.storage?.fsPath || null,
|
|
48
|
+
};
|
|
49
|
+
// --- SmartProxy ---
|
|
50
|
+
let acmeInfo = null;
|
|
51
|
+
if (opts.smartProxyConfig?.acme) {
|
|
52
|
+
const acme = opts.smartProxyConfig.acme;
|
|
53
|
+
acmeInfo = {
|
|
54
|
+
enabled: acme.enabled !== false,
|
|
55
|
+
accountEmail: acme.accountEmail || '',
|
|
56
|
+
useProduction: acme.useProduction !== false,
|
|
57
|
+
autoRenew: acme.autoRenew !== false,
|
|
58
|
+
renewThresholdDays: acme.renewThresholdDays || 30,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
let routeCount = 0;
|
|
62
|
+
if (dcRouter.routeConfigManager) {
|
|
63
|
+
try {
|
|
64
|
+
const merged = await dcRouter.routeConfigManager.getMergedRoutes();
|
|
65
|
+
routeCount = merged.routes.length;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
routeCount = opts.smartProxyConfig?.routes?.length || 0;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else if (opts.smartProxyConfig?.routes) {
|
|
72
|
+
routeCount = opts.smartProxyConfig.routes.length;
|
|
73
|
+
}
|
|
74
|
+
const smartProxy = {
|
|
75
|
+
enabled: !!dcRouter.smartProxy,
|
|
76
|
+
routeCount,
|
|
77
|
+
acme: acmeInfo,
|
|
78
|
+
};
|
|
79
|
+
// --- Email ---
|
|
80
|
+
let emailDomains = [];
|
|
81
|
+
if (dcRouter.emailServer && dcRouter.emailServer.domainRegistry) {
|
|
82
|
+
emailDomains = dcRouter.emailServer.domainRegistry.getAllDomains();
|
|
83
|
+
}
|
|
84
|
+
else if (opts.emailConfig?.domains) {
|
|
85
|
+
emailDomains = opts.emailConfig.domains.map((d) => typeof d === 'string' ? d : d.domain);
|
|
86
|
+
}
|
|
87
|
+
let portMapping = null;
|
|
88
|
+
if (opts.emailPortConfig?.portMapping) {
|
|
89
|
+
portMapping = {};
|
|
90
|
+
for (const [ext, int] of Object.entries(opts.emailPortConfig.portMapping)) {
|
|
91
|
+
portMapping[String(ext)] = int;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const email = {
|
|
95
|
+
enabled: !!dcRouter.emailServer,
|
|
96
|
+
ports: opts.emailConfig?.ports || [],
|
|
97
|
+
portMapping,
|
|
98
|
+
hostname: opts.emailConfig?.hostname || null,
|
|
99
|
+
domains: emailDomains,
|
|
100
|
+
emailRouteCount: opts.emailConfig?.routes?.length || 0,
|
|
101
|
+
receivedEmailsPath: opts.emailPortConfig?.receivedEmailsPath || null,
|
|
102
|
+
};
|
|
103
|
+
// --- DNS ---
|
|
104
|
+
const dnsRecords = (opts.dnsRecords || []).map(r => ({
|
|
105
|
+
name: r.name,
|
|
106
|
+
type: r.type,
|
|
107
|
+
value: r.value,
|
|
108
|
+
ttl: r.ttl,
|
|
109
|
+
}));
|
|
110
|
+
const dns = {
|
|
111
|
+
enabled: !!dcRouter.dnsServer,
|
|
112
|
+
port: 53,
|
|
113
|
+
nsDomains: opts.dnsNsDomains || [],
|
|
114
|
+
scopes: opts.dnsScopes || [],
|
|
115
|
+
recordCount: dnsRecords.length,
|
|
116
|
+
records: dnsRecords,
|
|
117
|
+
dnsChallenge: !!opts.dnsChallenge?.cloudflareApiKey,
|
|
118
|
+
};
|
|
119
|
+
// --- TLS ---
|
|
120
|
+
let tlsSource = 'none';
|
|
121
|
+
if (opts.tls?.certPath && opts.tls?.keyPath) {
|
|
122
|
+
tlsSource = 'static';
|
|
123
|
+
}
|
|
124
|
+
else if (opts.smartProxyConfig?.acme?.enabled !== false && opts.smartProxyConfig?.acme) {
|
|
125
|
+
tlsSource = 'acme';
|
|
126
|
+
}
|
|
127
|
+
const tls = {
|
|
128
|
+
contactEmail: opts.tls?.contactEmail || opts.smartProxyConfig?.acme?.accountEmail || null,
|
|
129
|
+
domain: opts.tls?.domain || null,
|
|
130
|
+
source: tlsSource,
|
|
131
|
+
certPath: opts.tls?.certPath || null,
|
|
132
|
+
keyPath: opts.tls?.keyPath || null,
|
|
133
|
+
};
|
|
134
|
+
// --- Cache ---
|
|
135
|
+
const cacheConfig = opts.cacheConfig;
|
|
136
|
+
const cache = {
|
|
137
|
+
enabled: cacheConfig?.enabled !== false,
|
|
138
|
+
storagePath: cacheConfig?.storagePath || resolvedPaths.defaultTsmDbPath,
|
|
139
|
+
dbName: cacheConfig?.dbName || 'dcrouter',
|
|
140
|
+
defaultTTLDays: cacheConfig?.defaultTTLDays || 30,
|
|
141
|
+
cleanupIntervalHours: cacheConfig?.cleanupIntervalHours || 1,
|
|
142
|
+
ttlConfig: cacheConfig?.ttlConfig ? { ...cacheConfig.ttlConfig } : {},
|
|
143
|
+
};
|
|
144
|
+
// --- RADIUS ---
|
|
145
|
+
const radiusCfg = opts.radiusConfig;
|
|
146
|
+
const radius = {
|
|
147
|
+
enabled: !!dcRouter.radiusServer,
|
|
148
|
+
authPort: radiusCfg?.authPort || null,
|
|
149
|
+
acctPort: radiusCfg?.acctPort || null,
|
|
150
|
+
bindAddress: radiusCfg?.bindAddress || null,
|
|
151
|
+
clientCount: radiusCfg?.clients?.length || 0,
|
|
152
|
+
vlanDefaultVlan: radiusCfg?.vlanAssignment?.defaultVlan ?? null,
|
|
153
|
+
vlanAllowUnknownMacs: radiusCfg?.vlanAssignment?.allowUnknownMacs ?? null,
|
|
154
|
+
vlanMappingCount: radiusCfg?.vlanAssignment?.mappings?.length || 0,
|
|
155
|
+
};
|
|
156
|
+
// --- Remote Ingress ---
|
|
157
|
+
const riCfg = opts.remoteIngressConfig;
|
|
158
|
+
const connectedEdgeIps = dcRouter.tunnelManager?.getConnectedEdgeIps() || [];
|
|
159
|
+
// Determine TLS mode: custom certs > ACME from cert store > self-signed fallback
|
|
160
|
+
let tlsMode = 'self-signed';
|
|
161
|
+
if (riCfg?.tls?.certPath && riCfg?.tls?.keyPath) {
|
|
162
|
+
tlsMode = 'custom';
|
|
163
|
+
}
|
|
164
|
+
else if (riCfg?.hubDomain) {
|
|
165
|
+
try {
|
|
166
|
+
const stored = await dcRouter.storageManager.getJSON(`/proxy-certs/${riCfg.hubDomain}`);
|
|
167
|
+
if (stored?.publicKey && stored?.privateKey) {
|
|
168
|
+
tlsMode = 'acme';
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
catch { /* no stored cert */ }
|
|
172
|
+
}
|
|
173
|
+
const remoteIngress = {
|
|
174
|
+
enabled: !!dcRouter.remoteIngressManager,
|
|
175
|
+
tunnelPort: riCfg?.tunnelPort || null,
|
|
176
|
+
hubDomain: riCfg?.hubDomain || null,
|
|
177
|
+
tlsMode,
|
|
178
|
+
connectedEdgeIps,
|
|
179
|
+
};
|
|
180
|
+
return {
|
|
181
|
+
system,
|
|
182
|
+
smartProxy,
|
|
183
|
+
email,
|
|
184
|
+
dns,
|
|
185
|
+
tls,
|
|
186
|
+
cache,
|
|
187
|
+
radius,
|
|
188
|
+
remoteIngress,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9vcHNzZXJ2ZXIvaGFuZGxlcnMvY29uZmlnLmhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBRXhDLE9BQU8sS0FBSyxVQUFVLE1BQU0saUNBQWlDLENBQUM7QUFFOUQsTUFBTSxPQUFPLGFBQWE7SUFDSjtJQUFwQixZQUFvQixZQUF1QjtRQUF2QixpQkFBWSxHQUFaLFlBQVksQ0FBVztRQUN6QyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRU8sZ0JBQWdCO1FBQ3RCLDRGQUE0RjtRQUM1RixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQztRQUU1Qyx3Q0FBd0M7UUFDeEMsTUFBTSxDQUFDLGVBQWUsQ0FDcEIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDbkMsa0JBQWtCLEVBQ2xCLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLEVBQUU7WUFDMUIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUM3QyxPQUFPO2dCQUNMLE1BQU07Z0JBQ04sT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPO2FBQ3pCLENBQUM7UUFDSixDQUFDLENBQ0YsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVPLEtBQUssQ0FBQyxnQkFBZ0I7UUFDNUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUM7UUFDL0MsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQztRQUM5QixNQUFNLGFBQWEsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDO1FBRTdDLGlCQUFpQjtRQUNqQixN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
|
|
@@ -0,0 +1,25 @@
|
|
|
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
|
+
}
|