@xenon-device-management/xenon 1.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.
- package/README.md +446 -0
- package/lib/package.json +207 -0
- package/lib/public/assets/Layouts-7IT8aFLI.js +11 -0
- package/lib/public/assets/Layouts-DPMls9vh.css +1 -0
- package/lib/public/assets/ai-settings-BbnfgdEx.js +11 -0
- package/lib/public/assets/apps-CRMrI4_p.js +16 -0
- package/lib/public/assets/apps-CcM77dgg.css +1 -0
- package/lib/public/assets/badge-B1nKs8zj.css +1 -0
- package/lib/public/assets/badge-CSvl5xIU.js +11 -0
- package/lib/public/assets/button-CJlKn4PZ.css +1 -0
- package/lib/public/assets/button-CvLaGFYj.js +26 -0
- package/lib/public/assets/calendar-6w-D6Oaw.js +6 -0
- package/lib/public/assets/clock-DcdeWBPr.js +6 -0
- package/lib/public/assets/cpu-DiSoXT9n.js +6 -0
- package/lib/public/assets/device-explorer-CajM63OJ.js +193 -0
- package/lib/public/assets/device-explorer-CxdUAoTL.css +1 -0
- package/lib/public/assets/index-ByQwMN5T.js +174 -0
- package/lib/public/assets/index-C1DBaoSh.js +1 -0
- package/lib/public/assets/index-qzCez_kk.css +1 -0
- package/lib/public/assets/lock-B23ibZmo.js +6 -0
- package/lib/public/assets/maintenance-settings-CirzA6yG.js +6 -0
- package/lib/public/assets/mouse-pointer-2-Cz76SHFb.js +6 -0
- package/lib/public/assets/plus-BBwlIevt.js +6 -0
- package/lib/public/assets/session-dashboard-C2k7FFv_.css +1 -0
- package/lib/public/assets/session-dashboard-HPDtwPOZ.js +62 -0
- package/lib/public/assets/settings-DrZsZwdc.js +1 -0
- package/lib/public/assets/trash-2-DQpvzJec.js +6 -0
- package/lib/public/assets/useSocket-Dxsqae2a.js +16 -0
- package/lib/public/assets/webhook-settings-CDPgsgkb.css +1 -0
- package/lib/public/assets/webhook-settings-Cp-B4Nrw.js +1 -0
- package/lib/public/assets/zap-DovP6iow.js +6 -0
- package/lib/public/favicon.ico +0 -0
- package/lib/public/favicon.png +0 -0
- package/lib/public/favicon.svg +9 -0
- package/lib/public/index.html +46 -0
- package/lib/public/logo.svg +17 -0
- package/lib/public/logo192.png +0 -0
- package/lib/public/logo512.png +0 -0
- package/lib/public/manifest.json +25 -0
- package/lib/public/robots.txt +3 -0
- package/lib/schema.json +348 -0
- package/lib/src/InternalHttpClient.js +212 -0
- package/lib/src/PluginContext.js +29 -0
- package/lib/src/XenonCapabilityManager.js +199 -0
- package/lib/src/app/index.js +167 -0
- package/lib/src/app/routers/apps.js +79 -0
- package/lib/src/app/routers/config.js +131 -0
- package/lib/src/app/routers/control.js +835 -0
- package/lib/src/app/routers/dashboard.js +301 -0
- package/lib/src/app/routers/grid.js +352 -0
- package/lib/src/app/routers/reservation.js +190 -0
- package/lib/src/app/routers/webhook.js +83 -0
- package/lib/src/app/swagger-docs.js +203 -0
- package/lib/src/app/swagger.js +366 -0
- package/lib/src/chromeUtils.js +148 -0
- package/lib/src/commands/handle.js +19 -0
- package/lib/src/commands/index.js +8 -0
- package/lib/src/config.js +73 -0
- package/lib/src/dashboard/asset-manager.js +84 -0
- package/lib/src/dashboard/commands.js +284 -0
- package/lib/src/dashboard/event-manager.js +699 -0
- package/lib/src/dashboard/services/app-service.js +134 -0
- package/lib/src/dashboard/services/failure-analysis-service.js +173 -0
- package/lib/src/dashboard/services/session-service.js +113 -0
- package/lib/src/data-service/CircuitBreaker.js +83 -0
- package/lib/src/data-service/config-service.js +155 -0
- package/lib/src/data-service/db.js +122 -0
- package/lib/src/data-service/device-service.js +320 -0
- package/lib/src/data-service/device-store.interface.js +2 -0
- package/lib/src/data-service/device-store.js +345 -0
- package/lib/src/data-service/pending-sessions-service.js +25 -0
- package/lib/src/data-service/pluginArgs.js +25 -0
- package/lib/src/data-service/prisma-service.js +31 -0
- package/lib/src/data-service/prisma-store.js +385 -0
- package/lib/src/data-service/queue-service.js +150 -0
- package/lib/src/data-service/web-config-service.js +130 -0
- package/lib/src/device-managers/AndroidDeviceManager.js +1155 -0
- package/lib/src/device-managers/ChromeDriverManager.js +68 -0
- package/lib/src/device-managers/HealthMonitorService.js +325 -0
- package/lib/src/device-managers/IOSDeviceManager.js +351 -0
- package/lib/src/device-managers/NodeDevices.js +82 -0
- package/lib/src/device-managers/android/AndroidStreamService.js +370 -0
- package/lib/src/device-managers/android/DeviceLockManager.js +45 -0
- package/lib/src/device-managers/cloud/CapabilityManager.js +26 -0
- package/lib/src/device-managers/cloud/Devices.js +86 -0
- package/lib/src/device-managers/iOSTracker.js +44 -0
- package/lib/src/device-managers/index.js +89 -0
- package/lib/src/device-managers/ios/IOSDiscoveryService.js +268 -0
- package/lib/src/device-managers/ios/IOSStreamService.js +893 -0
- package/lib/src/device-managers/ios/WDAClient.js +866 -0
- package/lib/src/device-utils.js +663 -0
- package/lib/src/enums/Capabilities.js +8 -0
- package/lib/src/enums/Cloud.js +11 -0
- package/lib/src/enums/Platform.js +9 -0
- package/lib/src/enums/SessionType.js +9 -0
- package/lib/src/enums/SocketEvents.js +15 -0
- package/lib/src/helpers/UniversalMjpegProxy.js +273 -0
- package/lib/src/helpers/index.js +229 -0
- package/lib/src/index.js +95 -0
- package/lib/src/interceptors/CommandInterceptor.js +524 -0
- package/lib/src/interfaces/ICloudManager.js +2 -0
- package/lib/src/interfaces/IDevice.js +2 -0
- package/lib/src/interfaces/IDeviceFilterOptions.js +2 -0
- package/lib/src/interfaces/IDeviceManager.js +2 -0
- package/lib/src/interfaces/IOptions.js +2 -0
- package/lib/src/interfaces/IPluginArgs.js +55 -0
- package/lib/src/interfaces/ISessionCapability.js +2 -0
- package/lib/src/logger.js +225 -0
- package/lib/src/plugin.js +244 -0
- package/lib/src/prisma.js +12 -0
- package/lib/src/profiling/AndroidAppProfiler.js +213 -0
- package/lib/src/proxy/wd-command-proxy.js +221 -0
- package/lib/src/scripts/generate-database-migration.js +59 -0
- package/lib/src/scripts/initialize-database.js +55 -0
- package/lib/src/scripts/install-go-ios.js +66 -0
- package/lib/src/scripts/prepare-prisma.js +89 -0
- package/lib/src/services/AICommandService.js +143 -0
- package/lib/src/services/AIService.js +466 -0
- package/lib/src/services/CleanupService.js +141 -0
- package/lib/src/services/EventBus.js +74 -0
- package/lib/src/services/InspectorService.js +395 -0
- package/lib/src/services/MetricsService.js +134 -0
- package/lib/src/services/NetworkConditioningService.js +173 -0
- package/lib/src/services/NotificationService.js +163 -0
- package/lib/src/services/RequestLogService.js +252 -0
- package/lib/src/services/ResourceIsolationService.js +122 -0
- package/lib/src/services/SecurityService.js +120 -0
- package/lib/src/services/ServerManager.js +284 -0
- package/lib/src/services/SessionHeartbeatService.js +158 -0
- package/lib/src/services/SessionLifecycleService.js +572 -0
- package/lib/src/services/SocketClient.js +71 -0
- package/lib/src/services/SocketServer.js +87 -0
- package/lib/src/services/TracingService.js +132 -0
- package/lib/src/services/VideoPipelineService.js +220 -0
- package/lib/src/services/healing/FuzzyXmlHealingProvider.js +333 -0
- package/lib/src/services/healing/HealEtalonService.js +98 -0
- package/lib/src/services/healing/HealedLocatorGenerator.js +132 -0
- package/lib/src/services/healing/HealingOrchestrator.js +165 -0
- package/lib/src/services/healing/LlmHealingProvider.js +77 -0
- package/lib/src/services/healing/OcrHealingProvider.js +119 -0
- package/lib/src/services/healing/ResilioTreeHealingProvider.js +100 -0
- package/lib/src/services/healing/VisualAiHealingProvider.js +90 -0
- package/lib/src/services/healing/types.js +12 -0
- package/lib/src/services/omni-vision/OmniVisionService.js +718 -0
- package/lib/src/services/omni-vision/VisionAssertionService.js +68 -0
- package/lib/src/sessions/CloudSession.js +42 -0
- package/lib/src/sessions/LocalSession.js +313 -0
- package/lib/src/sessions/RemoteSession.js +287 -0
- package/lib/src/sessions/SessionManager.js +238 -0
- package/lib/src/sessions/XenonSession.js +44 -0
- package/lib/src/types/CLIArgs.js +2 -0
- package/lib/src/types/CloudArgs.js +2 -0
- package/lib/src/types/CloudSchema.js +131 -0
- package/lib/src/types/DeviceType.js +2 -0
- package/lib/src/types/DeviceUpdate.js +2 -0
- package/lib/src/types/IOSDevice.js +2 -0
- package/lib/src/types/Platform.js +2 -0
- package/lib/src/types/SessionStatus.js +11 -0
- package/lib/src/validators/CapabilityValidator.js +93 -0
- package/lib/test/e2e/android/conf.spec.js +43 -0
- package/lib/test/e2e/android/conf2.spec.js +44 -0
- package/lib/test/e2e/android/conf3.spec.js +44 -0
- package/lib/test/e2e/e2ehelper.js +113 -0
- package/lib/test/e2e/hubnode/forward-request.spec.js +224 -0
- package/lib/test/e2e/hubnode/hubnode.spec.js +214 -0
- package/lib/test/e2e/ios/conf1.spec.js +39 -0
- package/lib/test/e2e/ios/conf2.spec.js +39 -0
- package/lib/test/e2e/plugin-harness.js +236 -0
- package/lib/test/e2e/plugin.spec.js +97 -0
- package/lib/test/e2e/telemetry_verification.spec.js +83 -0
- package/lib/test/e2e/video-recording-test.spec.js +63 -0
- package/lib/test/helpers/test-container.js +112 -0
- package/lib/test/integration/androidDevices.spec.js +137 -0
- package/lib/test/integration/cliArgs.js +73 -0
- package/lib/test/integration/ios/01iOSSimulator.spec.js +291 -0
- package/lib/test/integration/ios/02iOSDevices.spec.js +75 -0
- package/lib/test/integration/testHelpers.js +74 -0
- package/lib/test/unit/AndroidDeviceManager.spec.js +178 -0
- package/lib/test/unit/ChromeDriverManager.spec.js +26 -0
- package/lib/test/unit/CleanupService.spec.js +21 -0
- package/lib/test/unit/DeviceModel.spec.js +157 -0
- package/lib/test/unit/FuzzyXmlHealingProvider.test.js +294 -0
- package/lib/test/unit/GetAdbOriginal.js +42 -0
- package/lib/test/unit/HealingCascade.test.js +128 -0
- package/lib/test/unit/IOSDeviceManager.spec.js +261 -0
- package/lib/test/unit/RemoteIOs.spec.js +78 -0
- package/lib/test/unit/ResilioTreeHealingProvider.test.js +96 -0
- package/lib/test/unit/commands.spec.js +27 -0
- package/lib/test/unit/config.spec.js +27 -0
- package/lib/test/unit/device-service.spec.js +307 -0
- package/lib/test/unit/device-utils.spec.js +313 -0
- package/lib/test/unit/fixtures/device.config.js +4 -0
- package/lib/test/unit/fixtures/devices.js +89 -0
- package/lib/test/unit/helpers.spec.js +62 -0
- package/lib/test/unit/omni-vision.spec.js +100 -0
- package/lib/test/unit/plugin.spec.js +133 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +207 -0
- package/prisma/data.db +0 -0
- package/prisma/dev.db +0 -0
- package/prisma/dev.db-journal +0 -0
- package/prisma/migrations/20231011074725_initial_tables/migration.sql +47 -0
- package/prisma/migrations/20231226115334_update_session_log/migration.sql +2 -0
- package/prisma/migrations/20251204113710_add_video_recording_enabled/migration.sql +29 -0
- package/prisma/migrations/20251204132449_add_log_table/migration.sql +11 -0
- package/prisma/migrations/20251205050111_add_profiling_support/migration.sql +47 -0
- package/prisma/migrations/20251205050947_add_is_error_field/migration.sql +24 -0
- package/prisma/migrations/20260126201337_add_app_model/migration.sql +18 -0
- package/prisma/migrations/20260130115722_add_performance_trace_and_xenon_sync/migration.sql +2 -0
- package/prisma/migrations/20260130135114_add_device_models/migration.sql +57 -0
- package/prisma/migrations/20260130140655_make_systemport_optional/migration.sql +45 -0
- package/prisma/migrations/20260130140932_make_device_fields_optional/migration.sql +45 -0
- package/prisma/migrations/20260130141040_final_schema_fix/migration.sql +45 -0
- package/prisma/migrations/20260130143234_add_device_health_fields/migration.sql +4 -0
- package/prisma/migrations/20260130144921_add_failure_category/migration.sql +2 -0
- package/prisma/migrations/20260131151456_add_webhook_config/migration.sql +10 -0
- package/prisma/migrations/20260201094507_add_device_tags/migration.sql +11 -0
- package/prisma/migrations/20260201103410_add_managed_process/migration.sql +15 -0
- package/prisma/migrations/20260201140637_add_web_config/migration.sql +22 -0
- package/prisma/migrations/20260201162232_add_session_progress/migration.sql +2 -0
- package/prisma/migrations/20260201174231_add_total_healed_count/migration.sql +2 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +210 -0
- package/schema.json +348 -0
- package/scripts/build-xenon.sh +32 -0
- package/scripts/dev/debug-gemini.ts +44 -0
- package/scripts/generate-types-from-schema.js +86 -0
- package/scripts/install-compatible-driver.js +39 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ResourceIsolationService = void 0;
|
|
16
|
+
const typedi_1 = require("typedi");
|
|
17
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
18
|
+
const os_1 = __importDefault(require("os"));
|
|
19
|
+
/**
|
|
20
|
+
* ResourceIsolationService
|
|
21
|
+
* Provides abstraction for OS-level process sandboxing and priority management.
|
|
22
|
+
* Prevents "Noisy Neighbor" issues in high-density device farms.
|
|
23
|
+
*/
|
|
24
|
+
let ResourceIsolationService = class ResourceIsolationService {
|
|
25
|
+
constructor() {
|
|
26
|
+
this.isMac = os_1.default.platform() === 'darwin';
|
|
27
|
+
this.isLinux = os_1.default.platform() === 'linux';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Wraps a command string with OS-level isolation/priority prefixes.
|
|
31
|
+
* @param command The base command to execute
|
|
32
|
+
* @param profile The desired isolation profile
|
|
33
|
+
* @returns The wrapped command
|
|
34
|
+
*/
|
|
35
|
+
wrapCommand(command, profile) {
|
|
36
|
+
if (profile === 'Performance')
|
|
37
|
+
return command; // Default, no wrap needed
|
|
38
|
+
if (this.isMac) {
|
|
39
|
+
return this.wrapMacOS(command, profile);
|
|
40
|
+
}
|
|
41
|
+
if (this.isLinux) {
|
|
42
|
+
return this.wrapLinux(command, profile);
|
|
43
|
+
}
|
|
44
|
+
return command;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Specialized wrapper for child_process.spawn
|
|
48
|
+
*/
|
|
49
|
+
wrapSpawn(command, args, profile) {
|
|
50
|
+
if (profile === 'Performance')
|
|
51
|
+
return { command, args };
|
|
52
|
+
if (this.isMac) {
|
|
53
|
+
if (profile === 'Economy') {
|
|
54
|
+
return { command: 'taskpolicy', args: ['-c', 'background', command, ...args] };
|
|
55
|
+
}
|
|
56
|
+
if (profile === 'Guaranteed') {
|
|
57
|
+
return { command: 'nice', args: ['-n', '-5', command, ...args] };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (this.isLinux) {
|
|
61
|
+
if (profile === 'Economy') {
|
|
62
|
+
return { command: 'nice', args: ['-n', '19', command, ...args] };
|
|
63
|
+
}
|
|
64
|
+
if (profile === 'Guaranteed') {
|
|
65
|
+
return { command: 'nice', args: ['-n', '-10', command, ...args] };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return { command, args };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* macOS version using taskpolicy
|
|
72
|
+
* -c background: Moves process to background throttled state
|
|
73
|
+
* -p <pid>: Can also be used, but we wrap the spawn.
|
|
74
|
+
*/
|
|
75
|
+
wrapMacOS(command, profile) {
|
|
76
|
+
if (profile === 'Economy') {
|
|
77
|
+
// taskpolicy -c background is the most effective way to throttle CPU/IO on Mac
|
|
78
|
+
logger_1.default.debug('🛡️ Resource Isolation: Throttling command to background (Economy)');
|
|
79
|
+
return `taskpolicy -c background ${command}`;
|
|
80
|
+
}
|
|
81
|
+
if (profile === 'Guaranteed') {
|
|
82
|
+
// MacOS doesn't have a simple "High priority" CLI wrapper for spawn easily
|
|
83
|
+
// without sudo, but we can use 'nice'
|
|
84
|
+
logger_1.default.debug('🛡️ Resource Isolation: Assigning high priority (Guaranteed)');
|
|
85
|
+
return `nice -n -5 ${command}`;
|
|
86
|
+
}
|
|
87
|
+
return command;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Linux version using nice/renice
|
|
91
|
+
* Priority -20 (Highest) to 19 (Lowest)
|
|
92
|
+
*/
|
|
93
|
+
wrapLinux(command, profile) {
|
|
94
|
+
if (profile === 'Economy') {
|
|
95
|
+
logger_1.default.debug('🛡️ Resource Isolation: Throttling command (Economy)');
|
|
96
|
+
return `nice -n 19 ${command}`;
|
|
97
|
+
}
|
|
98
|
+
if (profile === 'Guaranteed') {
|
|
99
|
+
logger_1.default.debug('🛡️ Resource Isolation: Assigning high priority (Guaranteed)');
|
|
100
|
+
return `nice -n -10 ${command}`;
|
|
101
|
+
}
|
|
102
|
+
return command;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get numeric priority value for libraries that support it
|
|
106
|
+
*/
|
|
107
|
+
getPriority(profile) {
|
|
108
|
+
switch (profile) {
|
|
109
|
+
case 'Economy':
|
|
110
|
+
return 19;
|
|
111
|
+
case 'Guaranteed':
|
|
112
|
+
return -10;
|
|
113
|
+
default:
|
|
114
|
+
return 0;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
exports.ResourceIsolationService = ResourceIsolationService;
|
|
119
|
+
exports.ResourceIsolationService = ResourceIsolationService = __decorate([
|
|
120
|
+
(0, typedi_1.Service)(),
|
|
121
|
+
__metadata("design:paramtypes", [])
|
|
122
|
+
], ResourceIsolationService);
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
12
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
13
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
14
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
15
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
16
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
17
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
21
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
22
|
+
};
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.SecurityService = void 0;
|
|
25
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
26
|
+
const os_1 = __importDefault(require("os"));
|
|
27
|
+
const typedi_1 = require("typedi");
|
|
28
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
29
|
+
let SecurityService = class SecurityService {
|
|
30
|
+
constructor() {
|
|
31
|
+
this.algorithm = 'aes-256-gcm';
|
|
32
|
+
this.ivLength = 12;
|
|
33
|
+
this.saltLength = 16;
|
|
34
|
+
this.tagLength = 16;
|
|
35
|
+
this.keyLength = 32;
|
|
36
|
+
this.iterations = 10000;
|
|
37
|
+
this.encryptionKey = null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Derives a machine-unique encryption key.
|
|
41
|
+
* Uses hostname and MAC addresses to create a stable, unique seed.
|
|
42
|
+
*/
|
|
43
|
+
getMachineSecret() {
|
|
44
|
+
const interfaces = os_1.default.networkInterfaces();
|
|
45
|
+
const macs = Object.values(interfaces)
|
|
46
|
+
.flat()
|
|
47
|
+
.filter((iface) => iface && !iface.internal)
|
|
48
|
+
.map((iface) => iface.mac)
|
|
49
|
+
.sort()
|
|
50
|
+
.join(':');
|
|
51
|
+
return `${os_1.default.hostname()}-${macs}-xenon-v1`;
|
|
52
|
+
}
|
|
53
|
+
getEncryptionKey(salt) {
|
|
54
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
if (this.encryptionKey && salt.length === 0)
|
|
56
|
+
return this.encryptionKey;
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
crypto_1.default.pbkdf2(this.getMachineSecret(), salt, this.iterations, this.keyLength, 'sha256', (err, derivedKey) => {
|
|
59
|
+
if (err)
|
|
60
|
+
reject(err);
|
|
61
|
+
else
|
|
62
|
+
resolve(derivedKey);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
encrypt(text) {
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
try {
|
|
70
|
+
if (!text)
|
|
71
|
+
return text;
|
|
72
|
+
const salt = crypto_1.default.randomBytes(this.saltLength);
|
|
73
|
+
const iv = crypto_1.default.randomBytes(this.ivLength);
|
|
74
|
+
const key = yield this.getEncryptionKey(salt);
|
|
75
|
+
const cipher = crypto_1.default.createCipheriv(this.algorithm, key, iv);
|
|
76
|
+
const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);
|
|
77
|
+
const tag = cipher.getAuthTag();
|
|
78
|
+
// Format: salt:iv:tag:encrypted
|
|
79
|
+
return Buffer.concat([salt, iv, tag, encrypted]).toString('base64');
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
logger_1.default.error(`Encryption failed: ${err.message}`);
|
|
83
|
+
throw new Error('Security Error: Failed to encrypt sensitive data.');
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
decrypt(data) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
try {
|
|
90
|
+
if (!data || (!data.includes('==') && data.length < 50))
|
|
91
|
+
return data; // Primitive check if it's already plain text
|
|
92
|
+
const buffer = Buffer.from(data, 'base64');
|
|
93
|
+
const salt = buffer.subarray(0, this.saltLength);
|
|
94
|
+
const iv = buffer.subarray(this.saltLength, this.saltLength + this.ivLength);
|
|
95
|
+
const tag = buffer.subarray(this.saltLength + this.ivLength, this.saltLength + this.ivLength + this.tagLength);
|
|
96
|
+
const encrypted = buffer.subarray(this.saltLength + this.ivLength + this.tagLength);
|
|
97
|
+
const key = yield this.getEncryptionKey(salt);
|
|
98
|
+
const decipher = crypto_1.default.createDecipheriv(this.algorithm, key, iv);
|
|
99
|
+
decipher.setAuthTag(tag);
|
|
100
|
+
const decrypted = Buffer.concat([
|
|
101
|
+
decipher.update(encrypted),
|
|
102
|
+
decipher.final(),
|
|
103
|
+
]);
|
|
104
|
+
return decrypted.toString('utf8');
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
// If decryption fails, it might be legacy plain text.
|
|
108
|
+
// In production, we should log this but maybe return the original for migration?
|
|
109
|
+
// For now, let's assume if it fails it's either corrupt or plain text.
|
|
110
|
+
logger_1.default.debug(`Decryption failed (possibly plain text): ${err.message}`);
|
|
111
|
+
return data;
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
exports.SecurityService = SecurityService;
|
|
117
|
+
exports.SecurityService = SecurityService = __decorate([
|
|
118
|
+
(0, typedi_1.Service)(),
|
|
119
|
+
__metadata("design:paramtypes", [])
|
|
120
|
+
], SecurityService);
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
19
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
20
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
21
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
22
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
23
|
+
};
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
42
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
43
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
44
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
45
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
46
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
47
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
51
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
52
|
+
};
|
|
53
|
+
var ServerManager_1;
|
|
54
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.ServerManager = void 0;
|
|
56
|
+
const typedi_1 = require("typedi");
|
|
57
|
+
const uuid_1 = require("uuid");
|
|
58
|
+
const helpers_1 = require("../helpers");
|
|
59
|
+
const ip_1 = __importDefault(require("ip"));
|
|
60
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
61
|
+
// enable resolveJsonModule in tsconfig must be true for this to work
|
|
62
|
+
const package_json_1 = __importDefault(require("../../package.json"));
|
|
63
|
+
const IPluginArgs_1 = require("../interfaces/IPluginArgs");
|
|
64
|
+
const config_service_1 = require("../data-service/config-service");
|
|
65
|
+
const PluginContext_1 = require("../PluginContext");
|
|
66
|
+
const device_store_1 = require("../data-service/device-store");
|
|
67
|
+
const device_utils_1 = require("../device-utils");
|
|
68
|
+
const app_1 = require("../app");
|
|
69
|
+
const wd_command_proxy_1 = require("../proxy/wd-command-proxy");
|
|
70
|
+
const appium_adb_1 = require("appium-adb");
|
|
71
|
+
const ChromeDriverManager_1 = __importDefault(require("../device-managers/ChromeDriverManager"));
|
|
72
|
+
const AndroidDeviceManager_1 = __importDefault(require("../device-managers/AndroidDeviceManager"));
|
|
73
|
+
const IOSDeviceManager_1 = __importDefault(require("../device-managers/IOSDeviceManager"));
|
|
74
|
+
const device_managers_1 = require("../device-managers");
|
|
75
|
+
const pluginArgs_1 = require("../data-service/pluginArgs");
|
|
76
|
+
const NodeDevices_1 = __importDefault(require("../device-managers/NodeDevices"));
|
|
77
|
+
const SocketServer_1 = require("./SocketServer");
|
|
78
|
+
const SocketClient_1 = require("./SocketClient");
|
|
79
|
+
const TracingService_1 = require("./TracingService");
|
|
80
|
+
const plugin_1 = require("../plugin");
|
|
81
|
+
let ServerManager = ServerManager_1 = class ServerManager {
|
|
82
|
+
constructor() {
|
|
83
|
+
this.logger = logger_1.default.scope('ServerManager');
|
|
84
|
+
}
|
|
85
|
+
updateServer(expressApp, httpServer, cliArgs) {
|
|
86
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
this.logger.debug(`📱 Update server with CLI Args: ${JSON.stringify((0, helpers_1.redactSecrets)(cliArgs))}`);
|
|
88
|
+
const pluginArgs = yield this.resolvePluginArgs(cliArgs);
|
|
89
|
+
const nodeId = (0, uuid_1.v4)();
|
|
90
|
+
logger_1.default.banner(package_json_1.default.version, nodeId);
|
|
91
|
+
// Standardize static variable initialization
|
|
92
|
+
plugin_1.XenonPlugin.NODE_ID = nodeId;
|
|
93
|
+
plugin_1.XenonPlugin.port = cliArgs.port;
|
|
94
|
+
plugin_1.XenonPlugin.nodeBasePath = cliArgs.basePath || '';
|
|
95
|
+
const context = typedi_1.Container.get(PluginContext_1.PluginContext);
|
|
96
|
+
context.setContext(pluginArgs, cliArgs.port, nodeId, cliArgs.basePath || '');
|
|
97
|
+
yield this.syncDatabaseAndAIConfig(pluginArgs);
|
|
98
|
+
yield this.initializeCoreSubsystems(pluginArgs);
|
|
99
|
+
this.registerRoutes(expressApp, cliArgs, pluginArgs);
|
|
100
|
+
yield this.bootEmulators(pluginArgs);
|
|
101
|
+
this.registerDependenciesInContainer(pluginArgs, cliArgs, nodeId);
|
|
102
|
+
yield this.setupHubOrNode(pluginArgs, cliArgs, httpServer, nodeId);
|
|
103
|
+
yield this.setupMaintenanceCrons(pluginArgs);
|
|
104
|
+
// Principal Cleaning: Attempt to recover remote sessions before marking as failed
|
|
105
|
+
const { SessionManager } = yield Promise.resolve().then(() => __importStar(require('../sessions/SessionManager')));
|
|
106
|
+
const sessionManager = typedi_1.Container.get(SessionManager);
|
|
107
|
+
const recoveredCount = yield sessionManager.recoverActiveSessions(nodeId, plugin_1.XenonPlugin.nodeBasePath);
|
|
108
|
+
const recoveredSessionIds = sessionManager.getAllSessions().map((s) => s.getId());
|
|
109
|
+
if (recoveredCount > 0) {
|
|
110
|
+
logger_1.default.info(`🔄 Successfully recovered ${recoveredCount} remote sessions`);
|
|
111
|
+
}
|
|
112
|
+
// Cleanup any remaining zombie sessions
|
|
113
|
+
const { cleanupZombieSessions } = yield Promise.resolve().then(() => __importStar(require('../dashboard/services/session-service')));
|
|
114
|
+
yield cleanupZombieSessions(recoveredSessionIds);
|
|
115
|
+
// Initial device discovery poll to start managers and trackers
|
|
116
|
+
yield (0, device_utils_1.updateDeviceList)(pluginArgs.bindHostOrIp, pluginArgs.hub, pluginArgs.tlsRejectUnauthorized);
|
|
117
|
+
// remove stale devices
|
|
118
|
+
yield (0, device_utils_1.removeStaleDevices)(pluginArgs.bindHostOrIp, pluginArgs.tlsRejectUnauthorized);
|
|
119
|
+
this.logger.info(`🚀 Xenon will be served at http://${pluginArgs.bindHostOrIp}:${cliArgs.port}/xenon with id ${nodeId}`);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
resolvePluginArgs(cliArgs) {
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
const pluginConfigs = cliArgs.plugin;
|
|
125
|
+
const pluginArgs = Object.assign({}, IPluginArgs_1.DefaultPluginArgs, ((pluginConfigs === null || pluginConfigs === void 0 ? void 0 : pluginConfigs['xenon']) || {}));
|
|
126
|
+
try {
|
|
127
|
+
const persistedConfig = yield typedi_1.Container.get(config_service_1.ConfigService).loadConfig();
|
|
128
|
+
if (persistedConfig && Object.keys(persistedConfig).length > 0) {
|
|
129
|
+
this.logger.info('Loading persisted configuration', persistedConfig);
|
|
130
|
+
Object.assign(pluginArgs, persistedConfig);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
this.logger.warn(`Failed to load persisted config: ${err}`);
|
|
135
|
+
}
|
|
136
|
+
if (pluginArgs.bindHostOrIp === undefined) {
|
|
137
|
+
pluginArgs.bindHostOrIp = ip_1.default.address();
|
|
138
|
+
}
|
|
139
|
+
return pluginArgs;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
syncDatabaseAndAIConfig(pluginArgs) {
|
|
143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
const { updateConfig } = yield Promise.resolve().then(() => __importStar(require('../config')));
|
|
145
|
+
const update = {};
|
|
146
|
+
if (pluginArgs.databaseProvider) {
|
|
147
|
+
update.databaseProvider = pluginArgs.databaseProvider;
|
|
148
|
+
process.env.XENON_DB_PROVIDER = pluginArgs.databaseProvider;
|
|
149
|
+
}
|
|
150
|
+
if (pluginArgs.databaseUrl) {
|
|
151
|
+
update.databaseUrl = pluginArgs.databaseUrl;
|
|
152
|
+
process.env.DATABASE_URL = pluginArgs.databaseUrl;
|
|
153
|
+
}
|
|
154
|
+
if (pluginArgs.aiProvider) {
|
|
155
|
+
update.aiProvider = pluginArgs.aiProvider;
|
|
156
|
+
process.env.XENON_AI_PROVIDER = pluginArgs.aiProvider;
|
|
157
|
+
}
|
|
158
|
+
if (pluginArgs.aiModel) {
|
|
159
|
+
update.aiModel = pluginArgs.aiModel;
|
|
160
|
+
process.env.XENON_AI_MODEL = pluginArgs.aiModel;
|
|
161
|
+
}
|
|
162
|
+
if (pluginArgs.aiBaseUrl) {
|
|
163
|
+
update.aiBaseUrl = pluginArgs.aiBaseUrl;
|
|
164
|
+
process.env.XENON_AI_BASE_URL = pluginArgs.aiBaseUrl;
|
|
165
|
+
}
|
|
166
|
+
if (pluginArgs.geminiApiKey) {
|
|
167
|
+
update.geminiApiKey = pluginArgs.geminiApiKey;
|
|
168
|
+
process.env.GEMINI_API_KEY = pluginArgs.geminiApiKey;
|
|
169
|
+
}
|
|
170
|
+
if (pluginArgs.openaiApiKey) {
|
|
171
|
+
update.openaiApiKey = pluginArgs.openaiApiKey;
|
|
172
|
+
process.env.OPENAI_API_KEY = pluginArgs.openaiApiKey;
|
|
173
|
+
}
|
|
174
|
+
if (pluginArgs.anthropicApiKey) {
|
|
175
|
+
update.anthropicApiKey = pluginArgs.anthropicApiKey;
|
|
176
|
+
process.env.ANTHROPIC_API_KEY = pluginArgs.anthropicApiKey;
|
|
177
|
+
}
|
|
178
|
+
if (Object.keys(update).length > 0) {
|
|
179
|
+
this.logger.info('[Plugin] Synchronizing database config', update);
|
|
180
|
+
updateConfig(update);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
initializeCoreSubsystems(pluginArgs) {
|
|
185
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
186
|
+
yield (0, device_utils_1.initializeStorage)();
|
|
187
|
+
yield device_store_1.DeviceStoreFactory.getStore().clearStorage();
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
registerRoutes(expressApp, cliArgs, pluginArgs) {
|
|
191
|
+
expressApp.use('/xenon', (0, app_1.createRouter)(pluginArgs));
|
|
192
|
+
(0, wd_command_proxy_1.registerProxyMiddlware)(expressApp, cliArgs);
|
|
193
|
+
}
|
|
194
|
+
bootEmulators(pluginArgs) {
|
|
195
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
196
|
+
if (pluginArgs.emulators &&
|
|
197
|
+
pluginArgs.emulators.length > 0 &&
|
|
198
|
+
pluginArgs.platform.toLowerCase().includes('android')) {
|
|
199
|
+
this.logger.info('Emulators will be booted!!');
|
|
200
|
+
const adb = yield appium_adb_1.ADB.createADB({});
|
|
201
|
+
const array = pluginArgs.emulators || [];
|
|
202
|
+
yield Promise.all(array.map((arr) => adb.launchAVD(arr.avdName, arr)));
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
registerDependenciesInContainer(pluginArgs, cliArgs, nodeId) {
|
|
207
|
+
typedi_1.Container.set('DeviceStore', device_store_1.DeviceStoreFactory.getStore());
|
|
208
|
+
typedi_1.Container.set('PendingSessionStore', device_store_1.DeviceStoreFactory.getPendingSessionStore());
|
|
209
|
+
typedi_1.Container.set('CLIArgsStore', device_store_1.DeviceStoreFactory.getCLIArgsStore());
|
|
210
|
+
typedi_1.Container.set('HealEtalonStore', device_store_1.DeviceStoreFactory.getHealEtalonStore());
|
|
211
|
+
typedi_1.Container.set('AndroidDeviceManager', typedi_1.Container.get(AndroidDeviceManager_1.default));
|
|
212
|
+
typedi_1.Container.set('IOSDeviceManager', typedi_1.Container.get(IOSDeviceManager_1.default));
|
|
213
|
+
const deviceManager = typedi_1.Container.get(device_managers_1.XenonManager);
|
|
214
|
+
deviceManager.init();
|
|
215
|
+
// Optional Chrome Download
|
|
216
|
+
if (pluginArgs.skipChromeDownload === false) {
|
|
217
|
+
ChromeDriverManager_1.default.create()
|
|
218
|
+
.then((mgr) => typedi_1.Container.set(ChromeDriverManager_1.default, mgr))
|
|
219
|
+
.catch((err) => this.logger.error(`Failed to initialize ChromeDriverManager: ${err}`));
|
|
220
|
+
}
|
|
221
|
+
(0, pluginArgs_1.addCLIArgs)(cliArgs);
|
|
222
|
+
}
|
|
223
|
+
setupHubOrNode(pluginArgs, cliArgs, httpServer, nodeId) {
|
|
224
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
225
|
+
const hubArgument = pluginArgs.hub;
|
|
226
|
+
if (hubArgument !== undefined) {
|
|
227
|
+
this.logger.info(`📡 I'm a node and my hub is ${hubArgument}`);
|
|
228
|
+
yield (0, device_utils_1.setupCronUpdateDeviceList)(pluginArgs.bindHostOrIp, hubArgument, pluginArgs.sendNodeDevicesToHubIntervalMs, pluginArgs.tlsRejectUnauthorized);
|
|
229
|
+
// Handle graceful shutdown
|
|
230
|
+
['SIGINT', 'SIGTERM'].forEach((signal) => {
|
|
231
|
+
process.once(signal, () => __awaiter(this, void 0, void 0, function* () {
|
|
232
|
+
logger_1.default.info(`Received ${signal}, unregistering node from hub...`);
|
|
233
|
+
try {
|
|
234
|
+
yield new NodeDevices_1.default(hubArgument, pluginArgs.tlsRejectUnauthorized).unRegisterNode(pluginArgs.bindHostOrIp);
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
logger_1.default.error(`Error during node unregistration: ${err}`);
|
|
238
|
+
}
|
|
239
|
+
process.kill(process.pid, signal);
|
|
240
|
+
}));
|
|
241
|
+
});
|
|
242
|
+
// Initialize Socket Client to connect to Hub
|
|
243
|
+
const socketClient = typedi_1.Container.get(SocketClient_1.SocketClient);
|
|
244
|
+
socketClient.initialize(hubArgument, pluginArgs.bindHostOrIp);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
ServerManager_1.IS_HUB = true;
|
|
248
|
+
this.logger.info(`🌐 I'm a hub and I'm listening on ${pluginArgs.bindHostOrIp}:${cliArgs.port}`);
|
|
249
|
+
const socketServer = typedi_1.Container.get(SocketServer_1.SocketServer);
|
|
250
|
+
socketServer.initialize(httpServer);
|
|
251
|
+
const tracingService = typedi_1.Container.get(TracingService_1.TracingService);
|
|
252
|
+
tracingService.initialize();
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
setupMaintenanceCrons(pluginArgs) {
|
|
257
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
258
|
+
var _a;
|
|
259
|
+
if (!((_a = pluginArgs.cloud) === null || _a === void 0 ? void 0 : _a.cloudName)) {
|
|
260
|
+
// 1. Check for stale nodes
|
|
261
|
+
yield (0, device_utils_1.setupCronCheckStaleDevices)(pluginArgs.checkStaleDevicesIntervalMs, pluginArgs.bindHostOrIp, pluginArgs.tlsRejectUnauthorized);
|
|
262
|
+
// 2. Release blocked devices
|
|
263
|
+
yield (0, device_utils_1.setupCronReleaseBlockedDevices)(pluginArgs.checkBlockedDevicesIntervalMs, pluginArgs.newCommandTimeoutSec);
|
|
264
|
+
// 3. Clean up pending sessions
|
|
265
|
+
yield (0, device_utils_1.setupCronCleanPendingSessions)(pluginArgs.checkBlockedDevicesIntervalMs, pluginArgs.deviceAvailabilityTimeoutMs + 10000);
|
|
266
|
+
// 4. Clean up expired reservations every 1 minute
|
|
267
|
+
yield (0, device_utils_1.setupCronCleanExpiredReservations)(60000);
|
|
268
|
+
// 5. Clean up older builds and sessions
|
|
269
|
+
yield (0, device_utils_1.setupCronCleanupBuilds)(pluginArgs);
|
|
270
|
+
// 6. Start Health Monitor Service
|
|
271
|
+
const { HealthMonitorService } = yield Promise.resolve().then(() => __importStar(require('../device-managers/HealthMonitorService')));
|
|
272
|
+
typedi_1.Container.get(HealthMonitorService).start(pluginArgs);
|
|
273
|
+
// 7. Start Session Heartbeat Service
|
|
274
|
+
const { SessionHeartbeatService } = yield Promise.resolve().then(() => __importStar(require('./SessionHeartbeatService')));
|
|
275
|
+
typedi_1.Container.get(SessionHeartbeatService).start(pluginArgs);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
exports.ServerManager = ServerManager;
|
|
281
|
+
ServerManager.IS_HUB = false;
|
|
282
|
+
exports.ServerManager = ServerManager = ServerManager_1 = __decorate([
|
|
283
|
+
(0, typedi_1.Service)()
|
|
284
|
+
], ServerManager);
|