@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,301 @@
|
|
|
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 __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
const prisma_1 = require("../../prisma");
|
|
46
|
+
const SessionManager_1 = require("../../sessions/SessionManager");
|
|
47
|
+
const UniversalMjpegProxy_1 = require("../../helpers/UniversalMjpegProxy");
|
|
48
|
+
const web_config_service_1 = require("../../data-service/web-config-service");
|
|
49
|
+
const typedi_1 = require("typedi");
|
|
50
|
+
const MJPEG_PROXY_CACHE = new Map();
|
|
51
|
+
//session guard
|
|
52
|
+
function isValidSession(request, response, next) {
|
|
53
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
const sessionId = request.params.sessionId;
|
|
55
|
+
// Principal Robustness: Allow virtual manual sessions
|
|
56
|
+
if (sessionId && sessionId.startsWith('manual_')) {
|
|
57
|
+
return next();
|
|
58
|
+
}
|
|
59
|
+
const session = yield prisma_1.prisma.session.findFirst({
|
|
60
|
+
where: {
|
|
61
|
+
id: sessionId,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
if (!session) {
|
|
65
|
+
return response.status(404).send({
|
|
66
|
+
error: true,
|
|
67
|
+
message: `Session with id ${sessionId} not found`,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
return next();
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
function getSessions(request, response) {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
const { buildId, query, status, platform } = request.query;
|
|
78
|
+
const where = {};
|
|
79
|
+
if (buildId) {
|
|
80
|
+
where.build_id = buildId;
|
|
81
|
+
}
|
|
82
|
+
if (status) {
|
|
83
|
+
where.status = status;
|
|
84
|
+
}
|
|
85
|
+
if (platform) {
|
|
86
|
+
where.device_platform = platform;
|
|
87
|
+
}
|
|
88
|
+
if (query) {
|
|
89
|
+
where.OR = [
|
|
90
|
+
{ id: { contains: query } },
|
|
91
|
+
{ name: { contains: query } },
|
|
92
|
+
{ device_udid: { contains: query } },
|
|
93
|
+
{ device_name: { contains: query } },
|
|
94
|
+
{ failure_category: { contains: query } },
|
|
95
|
+
{ tags: { contains: query } },
|
|
96
|
+
];
|
|
97
|
+
}
|
|
98
|
+
const sessions = yield prisma_1.prisma.session.findMany({
|
|
99
|
+
orderBy: {
|
|
100
|
+
createdAt: 'desc',
|
|
101
|
+
},
|
|
102
|
+
where,
|
|
103
|
+
take: 500,
|
|
104
|
+
});
|
|
105
|
+
return response.status(200).json(sessions);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function getBuilds(request, response) {
|
|
109
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
const builds = yield prisma_1.prisma.build.findMany({
|
|
111
|
+
orderBy: {
|
|
112
|
+
createdAt: 'desc',
|
|
113
|
+
},
|
|
114
|
+
include: {
|
|
115
|
+
_count: {
|
|
116
|
+
select: { sessions: true },
|
|
117
|
+
},
|
|
118
|
+
sessions: {
|
|
119
|
+
select: {
|
|
120
|
+
status: true,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
// Principal formatting: Add a flat summary object for the frontend
|
|
126
|
+
const formattedBuilds = builds.map((b) => (Object.assign(Object.assign({}, b), { sessionCount: b._count.sessions, passedCount: b.sessions.filter((s) => ['success', 'passed'].includes(s.status)).length, failedCount: b.sessions.filter((s) => s.status === 'failed').length, runningCount: b.sessions.filter((s) => s.status === 'running').length, sessions: undefined })));
|
|
127
|
+
return response.status(200).json(formattedBuilds);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function getSessionLogs(request, response) {
|
|
131
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
132
|
+
const sessionId = request.params.sessionId;
|
|
133
|
+
const logs = yield prisma_1.prisma.sessionLog.findMany({
|
|
134
|
+
orderBy: {
|
|
135
|
+
createdAt: 'desc',
|
|
136
|
+
},
|
|
137
|
+
where: {
|
|
138
|
+
session_id: sessionId,
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
return response.status(200).json(logs);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function getDeviceLogs(request, response) {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
const sessionId = request.params.sessionId;
|
|
147
|
+
const logs = yield prisma_1.prisma.log.findMany({
|
|
148
|
+
orderBy: {
|
|
149
|
+
createdAt: 'asc',
|
|
150
|
+
},
|
|
151
|
+
where: {
|
|
152
|
+
session_id: sessionId,
|
|
153
|
+
log_type: 'DEVICE',
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
return response.status(200).json(logs);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function getDebugLogs(request, response) {
|
|
160
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
161
|
+
const sessionId = request.params.sessionId;
|
|
162
|
+
const logs = yield prisma_1.prisma.log.findMany({
|
|
163
|
+
orderBy: {
|
|
164
|
+
createdAt: 'asc',
|
|
165
|
+
},
|
|
166
|
+
where: {
|
|
167
|
+
session_id: sessionId,
|
|
168
|
+
log_type: 'DEBUG',
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
return response.status(200).json(logs);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
function getProfilingData(request, response) {
|
|
175
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
176
|
+
const sessionId = request.params.sessionId;
|
|
177
|
+
const profilingData = yield prisma_1.prisma.profiling.findMany({
|
|
178
|
+
orderBy: {
|
|
179
|
+
timestamp: 'asc',
|
|
180
|
+
},
|
|
181
|
+
where: {
|
|
182
|
+
session_id: sessionId,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
return response.status(200).json(profilingData);
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
function streamLiveSessionVideo(request, response) {
|
|
189
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
190
|
+
var _a;
|
|
191
|
+
const sessionId = request.params.sessionId;
|
|
192
|
+
const session = SessionManager_1.SESSION_MANAGER.getSession(sessionId);
|
|
193
|
+
const videoUrl = session === null || session === void 0 ? void 0 : session.getLiveVideoUrl();
|
|
194
|
+
if (videoUrl) {
|
|
195
|
+
if (!MJPEG_PROXY_CACHE.has(sessionId)) {
|
|
196
|
+
MJPEG_PROXY_CACHE.set(sessionId, new UniversalMjpegProxy_1.UniversalMjpegProxy(videoUrl));
|
|
197
|
+
}
|
|
198
|
+
// Principal Robustness: Ensure proxy is updated if URL changes
|
|
199
|
+
const existingProxy = MJPEG_PROXY_CACHE.get(sessionId);
|
|
200
|
+
if (existingProxy && existingProxy.mjpegUrl !== videoUrl) {
|
|
201
|
+
MJPEG_PROXY_CACHE.set(sessionId, new UniversalMjpegProxy_1.UniversalMjpegProxy(videoUrl));
|
|
202
|
+
}
|
|
203
|
+
(_a = MJPEG_PROXY_CACHE.get(sessionId)) === null || _a === void 0 ? void 0 : _a.proxyRequest(request, response);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
return response.status(500).send({
|
|
207
|
+
error: true,
|
|
208
|
+
message: `Live video not available for session with id ${sessionId}`,
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function getGlobalConfig(request, response) {
|
|
214
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
215
|
+
try {
|
|
216
|
+
const dbConfig = yield typedi_1.Container.get(web_config_service_1.WebConfigService).getConfig();
|
|
217
|
+
// Merge with Environment Config (AI Settings)
|
|
218
|
+
const { config } = yield Promise.resolve().then(() => __importStar(require('../../config')));
|
|
219
|
+
// Sanitize keys - return boolean existence only
|
|
220
|
+
const aiConfig = {
|
|
221
|
+
aiProvider: config.aiProvider,
|
|
222
|
+
aiModel: config.aiModel,
|
|
223
|
+
aiBaseUrl: config.aiBaseUrl,
|
|
224
|
+
geminiModel: config.geminiModel,
|
|
225
|
+
openaiModel: config.openaiModel,
|
|
226
|
+
anthropicModel: config.anthropicModel,
|
|
227
|
+
ollamaModel: config.ollamaModel,
|
|
228
|
+
geminiSet: !!config.geminiApiKey,
|
|
229
|
+
openaiSet: !!config.openaiApiKey,
|
|
230
|
+
anthropicSet: !!config.anthropicApiKey,
|
|
231
|
+
};
|
|
232
|
+
return response.status(200).json(Object.assign(Object.assign({}, dbConfig), aiConfig));
|
|
233
|
+
}
|
|
234
|
+
catch (err) {
|
|
235
|
+
return response.status(500).json({ error: true, message: err.message });
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function updateGlobalConfig(request, response) {
|
|
240
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
241
|
+
try {
|
|
242
|
+
const payload = request.body;
|
|
243
|
+
// Handle Runtime AI Config Overrides (Memory only)
|
|
244
|
+
// Only pass defined values to avoid overwriting env vars (e.g. aiBaseUrl, ollamaModel) with undefined
|
|
245
|
+
const runtimeOverrides = {};
|
|
246
|
+
if (payload.aiProvider !== undefined)
|
|
247
|
+
runtimeOverrides.aiProvider = payload.aiProvider;
|
|
248
|
+
if (payload.aiModel !== undefined)
|
|
249
|
+
runtimeOverrides.aiModel = payload.aiModel;
|
|
250
|
+
if (payload.aiBaseUrl !== undefined)
|
|
251
|
+
runtimeOverrides.aiBaseUrl = payload.aiBaseUrl;
|
|
252
|
+
if (payload.geminiModel !== undefined)
|
|
253
|
+
runtimeOverrides.geminiModel = payload.geminiModel;
|
|
254
|
+
if (payload.openaiModel !== undefined)
|
|
255
|
+
runtimeOverrides.openaiModel = payload.openaiModel;
|
|
256
|
+
if (payload.anthropicModel !== undefined)
|
|
257
|
+
runtimeOverrides.anthropicModel = payload.anthropicModel;
|
|
258
|
+
if (payload.ollamaModel !== undefined)
|
|
259
|
+
runtimeOverrides.ollamaModel = payload.ollamaModel;
|
|
260
|
+
if (Object.keys(runtimeOverrides).length > 0) {
|
|
261
|
+
const { updateConfig } = yield Promise.resolve().then(() => __importStar(require('../../config')));
|
|
262
|
+
updateConfig(runtimeOverrides);
|
|
263
|
+
}
|
|
264
|
+
// Persist Web Configs to DB
|
|
265
|
+
yield typedi_1.Container.get(web_config_service_1.WebConfigService).setConfig(payload);
|
|
266
|
+
return response.status(200).json({ success: true });
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
return response.status(500).json({ error: true, message: err.message });
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
function resetMetrics(request, response) {
|
|
274
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
275
|
+
try {
|
|
276
|
+
const { DeviceStoreFactory } = yield Promise.resolve().then(() => __importStar(require('../../data-service/device-store')));
|
|
277
|
+
const store = DeviceStoreFactory.getStore();
|
|
278
|
+
yield store.resetMetrics();
|
|
279
|
+
return response.status(200).json({ success: true });
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
return response.status(500).json({ error: true, message: err.message });
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function register(router) {
|
|
287
|
+
router.use('/session/:sessionId', isValidSession);
|
|
288
|
+
router.get('/session', getSessions);
|
|
289
|
+
router.get('/build', getBuilds);
|
|
290
|
+
router.get('/session/:sessionId/live_video', streamLiveSessionVideo);
|
|
291
|
+
router.get('/session/:sessionId/session_log', getSessionLogs);
|
|
292
|
+
router.get('/session/:sessionId/logs/device', getDeviceLogs);
|
|
293
|
+
router.get('/session/:sessionId/logs/debug', getDebugLogs);
|
|
294
|
+
router.get('/session/:sessionId/profiling', getProfilingData);
|
|
295
|
+
router.get('/config', getGlobalConfig);
|
|
296
|
+
router.post('/config', updateGlobalConfig);
|
|
297
|
+
router.post('/config/reset-metrics', resetMetrics);
|
|
298
|
+
}
|
|
299
|
+
exports.default = {
|
|
300
|
+
register,
|
|
301
|
+
};
|
|
@@ -0,0 +1,352 @@
|
|
|
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 __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
const device_store_1 = require("../../data-service/device-store");
|
|
49
|
+
const queue_service_1 = require("../../data-service/queue-service");
|
|
50
|
+
const InternalHttpClient_1 = require("../../InternalHttpClient");
|
|
51
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
52
|
+
const device_service_1 = require("../../data-service/device-service");
|
|
53
|
+
const logger_1 = __importDefault(require("../../logger"));
|
|
54
|
+
const device_managers_1 = require("../../device-managers");
|
|
55
|
+
const typedi_1 = require("typedi");
|
|
56
|
+
const store = device_store_1.DeviceStoreFactory.getStore();
|
|
57
|
+
const pendingStore = device_store_1.DeviceStoreFactory.getPendingSessionStore();
|
|
58
|
+
const SERVER_UP_TIME = new Date().toISOString();
|
|
59
|
+
function getDevices(request, response) {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
var _a;
|
|
62
|
+
let devices = yield store.getAllDevices();
|
|
63
|
+
const { sessionId } = request.query;
|
|
64
|
+
if (sessionId) {
|
|
65
|
+
return response.json(devices.find((value) => value.session_id === sessionId));
|
|
66
|
+
}
|
|
67
|
+
/* dashboard-plugin-url is the base url for opening the appium-dashboard-plugin
|
|
68
|
+
* This value will be attached to all express request via middleware
|
|
69
|
+
*/
|
|
70
|
+
const dashboardPluginUrl = request['dashboard-plugin-url'];
|
|
71
|
+
if (dashboardPluginUrl) {
|
|
72
|
+
const response = yield InternalHttpClient_1.InternalHttpClient.get(`${dashboardPluginUrl}/api/sessions?start_time=${SERVER_UP_TIME}`);
|
|
73
|
+
const sessions = ((_a = response === null || response === void 0 ? void 0 : response.result) === null || _a === void 0 ? void 0 : _a.rows) || [];
|
|
74
|
+
const deviceSessionMap = {};
|
|
75
|
+
sessions.forEach((session) => {
|
|
76
|
+
if (!deviceSessionMap[session.udid]) {
|
|
77
|
+
deviceSessionMap[session.udid] = [];
|
|
78
|
+
}
|
|
79
|
+
deviceSessionMap[session.udid].push(session);
|
|
80
|
+
});
|
|
81
|
+
devices = devices.map((d) => {
|
|
82
|
+
var _a;
|
|
83
|
+
d.dashboard_link = `${dashboardPluginUrl}?device_udid=${d.udid}&start_time=${SERVER_UP_TIME}`;
|
|
84
|
+
d.total_session_count = ((_a = deviceSessionMap[d.udid]) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
85
|
+
return d;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return response.json(devices);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function getDeviceByPlatform(request, response) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
const { platform } = request.params;
|
|
94
|
+
const { deviceType, booted } = request.query;
|
|
95
|
+
if (!platform || ['ios', 'android'].indexOf(platform.toLowerCase()) < 0) {
|
|
96
|
+
return response.status(200).send([]);
|
|
97
|
+
}
|
|
98
|
+
let devices = yield store.findDevices({
|
|
99
|
+
platform: platform.toLowerCase(),
|
|
100
|
+
});
|
|
101
|
+
if (!lodash_1.default.isNil(deviceType)) {
|
|
102
|
+
devices = devices.filter((value) => value.deviceType === deviceType);
|
|
103
|
+
}
|
|
104
|
+
if (!lodash_1.default.isNil(booted)) {
|
|
105
|
+
devices = devices.filter((d) => d.state === 'Booted');
|
|
106
|
+
}
|
|
107
|
+
return response.status(200).send(devices);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function registerNode(request, response) {
|
|
111
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
112
|
+
const requestBody = request.body;
|
|
113
|
+
const { type } = request.query;
|
|
114
|
+
if (type === 'add') {
|
|
115
|
+
const addedDevices = yield (0, device_service_1.addNewDevice)(requestBody);
|
|
116
|
+
if (addedDevices.length > 0) {
|
|
117
|
+
logger_1.default.info(`Added new devices: ${JSON.stringify(addedDevices)}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else if (type === 'remove') {
|
|
121
|
+
yield (0, device_service_1.removeDevice)(requestBody);
|
|
122
|
+
}
|
|
123
|
+
else if (type === 'unregister') {
|
|
124
|
+
const { host } = request.query;
|
|
125
|
+
if (host) {
|
|
126
|
+
yield (0, device_service_1.removeDevicesByHost)(host);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
response.status(200).send({
|
|
130
|
+
success: true,
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function blockDevice(request, response) {
|
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
const requestBody = request.body;
|
|
137
|
+
const device = yield (0, device_service_1.getDevice)(requestBody);
|
|
138
|
+
if (!lodash_1.default.isNil(device)) {
|
|
139
|
+
yield (0, device_service_1.userBlockDevice)(device.udid, device.host);
|
|
140
|
+
}
|
|
141
|
+
response.status(200).send({
|
|
142
|
+
success: true,
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
function unBlockDevice(request, response) {
|
|
147
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
148
|
+
const requestBody = request.body;
|
|
149
|
+
const device = yield (0, device_service_1.getDevice)(requestBody);
|
|
150
|
+
if (!lodash_1.default.isNil(device)) {
|
|
151
|
+
yield (0, device_service_1.userUnblockDevice)(device.udid, device.host);
|
|
152
|
+
}
|
|
153
|
+
response.status(200).send({
|
|
154
|
+
success: true,
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function getQueuedSessionLength(request, response) {
|
|
159
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
160
|
+
response.json((yield pendingStore.getAllPendingSessions()).length);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function getQueuedSessionRequests(request, response) {
|
|
164
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
165
|
+
response.json(yield pendingStore.getAllPendingSessions());
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function getNodes(request, response) {
|
|
169
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
170
|
+
const allDevices = yield store.getAllDevices();
|
|
171
|
+
const nodes = allDevices.map((node) => node.host);
|
|
172
|
+
// unique nodes
|
|
173
|
+
const uniqueNodes = lodash_1.default.uniq(nodes);
|
|
174
|
+
response.json(uniqueNodes);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function getQueueStatusById(request, response) {
|
|
178
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
const status = yield typedi_1.Container.get(queue_service_1.QueueService).getQueueStatus(request.params.capability_id);
|
|
180
|
+
if (!status) {
|
|
181
|
+
return response.status(404).json({ error: 'Pending session not found' });
|
|
182
|
+
}
|
|
183
|
+
response.json(status);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
function getQueueSummary(request, response) {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
const summary = yield typedi_1.Container.get(queue_service_1.QueueService).getQueueSummary();
|
|
189
|
+
response.json(summary);
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
function nodeAdbStatusOnOtherHost(currentHost, request, response) {
|
|
193
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
194
|
+
const { host } = request.params;
|
|
195
|
+
// when host is this hub, return status from AndroidDeviceManager directly
|
|
196
|
+
// otherwise, forward request to the node
|
|
197
|
+
logger_1.default.info(`currentHost: ${currentHost}, host: ${host}`);
|
|
198
|
+
if (host === currentHost) {
|
|
199
|
+
const devices = yield getDevicesFromDeviceManager();
|
|
200
|
+
response.json(devices.map((device) => {
|
|
201
|
+
return {
|
|
202
|
+
udid: device.udid,
|
|
203
|
+
host: device.host,
|
|
204
|
+
state: device.state,
|
|
205
|
+
platform: device.platform,
|
|
206
|
+
};
|
|
207
|
+
}));
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
// find node url from database of devices
|
|
211
|
+
const devices = yield store.findDevices({ host: { $contains: host } });
|
|
212
|
+
if (devices.length === 0) {
|
|
213
|
+
response
|
|
214
|
+
.status(404)
|
|
215
|
+
.send(`Host ${host} does not have any devices listed in database. I don't know how to forward request to that host`);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const device = devices[0];
|
|
219
|
+
// remove wd/hub from url
|
|
220
|
+
const normalizedUrl = device.host.replace(/\/wd\/hub$/, '');
|
|
221
|
+
const url = `${normalizedUrl}/xenon/api/node/status`;
|
|
222
|
+
const result = yield InternalHttpClient_1.InternalHttpClient.get(url);
|
|
223
|
+
response.json(result);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
function nodeAdbStatusOnThisHost(request, response) {
|
|
228
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
+
const devices = yield getDevicesFromDeviceManager();
|
|
230
|
+
// return udid, host, state
|
|
231
|
+
response.json(devices.map((device) => {
|
|
232
|
+
return {
|
|
233
|
+
udid: device.udid,
|
|
234
|
+
host: device.host,
|
|
235
|
+
state: device.state,
|
|
236
|
+
platform: device.platform,
|
|
237
|
+
};
|
|
238
|
+
}));
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Returns all devices from all device managers (this host only)
|
|
243
|
+
* @returns IDevice[]
|
|
244
|
+
*/
|
|
245
|
+
function getDevicesFromDeviceManager() {
|
|
246
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
247
|
+
const dfm = typedi_1.Container.get(device_managers_1.XenonManager);
|
|
248
|
+
const instances = yield dfm.deviceInstances();
|
|
249
|
+
// return devices from all device managers
|
|
250
|
+
const devices = [];
|
|
251
|
+
for (const instance of instances) {
|
|
252
|
+
const instanceDevices = yield instance.getDevices({
|
|
253
|
+
androidDeviceType: 'both',
|
|
254
|
+
iosDeviceType: 'both',
|
|
255
|
+
}, []);
|
|
256
|
+
devices.push(...instanceDevices);
|
|
257
|
+
}
|
|
258
|
+
return devices;
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
function updateTags(request, response) {
|
|
262
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
263
|
+
const { udid, host, tags } = request.body;
|
|
264
|
+
if (!udid || !host || !Array.isArray(tags)) {
|
|
265
|
+
return response.status(400).json({ error: 'Missing udid, host, or tags array' });
|
|
266
|
+
}
|
|
267
|
+
yield (0, device_service_1.updateDeviceTags)(udid, host, tags);
|
|
268
|
+
response.status(200).json({ success: true });
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Returns active session statistics
|
|
273
|
+
*/
|
|
274
|
+
function getActiveSessions(request, response) {
|
|
275
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
276
|
+
const { SessionManager } = yield Promise.resolve().then(() => __importStar(require('../../sessions/SessionManager')));
|
|
277
|
+
const sessionManager = typedi_1.Container.get(SessionManager);
|
|
278
|
+
const stats = sessionManager.getStats();
|
|
279
|
+
const sessions = sessionManager.getAllSessions().map((s) => {
|
|
280
|
+
var _a, _b, _c;
|
|
281
|
+
return ({
|
|
282
|
+
id: s.getId(),
|
|
283
|
+
type: s.getType(),
|
|
284
|
+
deviceUdid: (_a = s.getDevice()) === null || _a === void 0 ? void 0 : _a.udid,
|
|
285
|
+
deviceName: (_b = s.getDevice()) === null || _b === void 0 ? void 0 : _b.name,
|
|
286
|
+
platform: (_c = s.getDevice()) === null || _c === void 0 ? void 0 : _c.platform,
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
response.json({
|
|
290
|
+
stats,
|
|
291
|
+
sessions,
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Returns HTTP request logs for debugging
|
|
297
|
+
*/
|
|
298
|
+
function getRequestLogs(request, response) {
|
|
299
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
300
|
+
const { RequestLogService } = yield Promise.resolve().then(() => __importStar(require('../../services/RequestLogService')));
|
|
301
|
+
const logService = typedi_1.Container.get(RequestLogService);
|
|
302
|
+
const limit = parseInt(request.query.limit) || 50;
|
|
303
|
+
const method = request.query.method;
|
|
304
|
+
const urlPattern = request.query.url;
|
|
305
|
+
const hasError = request.query.hasError === 'true'
|
|
306
|
+
? true
|
|
307
|
+
: request.query.hasError === 'false'
|
|
308
|
+
? false
|
|
309
|
+
: undefined;
|
|
310
|
+
const logs = logService.getRecentLogs(limit, {
|
|
311
|
+
method,
|
|
312
|
+
urlPattern,
|
|
313
|
+
hasError,
|
|
314
|
+
});
|
|
315
|
+
const stats = logService.getStats();
|
|
316
|
+
response.json({
|
|
317
|
+
stats,
|
|
318
|
+
logs,
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
function register(router, pluginArgs) {
|
|
323
|
+
router.get('/devices', getDevices);
|
|
324
|
+
router.get('/device', getDevices);
|
|
325
|
+
router.get('/device/:platform', getDeviceByPlatform);
|
|
326
|
+
router.post('/register', registerNode);
|
|
327
|
+
router.post('/block', blockDevice);
|
|
328
|
+
router.post('/unblock', unBlockDevice);
|
|
329
|
+
router.post('/device/tags', updateTags);
|
|
330
|
+
// session related
|
|
331
|
+
router.get('/queue/length', getQueuedSessionLength);
|
|
332
|
+
router.get('/queue', getQueuedSessionRequests);
|
|
333
|
+
router.get('/queue/status/:capability_id', getQueueStatusById);
|
|
334
|
+
router.get('/queue/summary', getQueueSummary);
|
|
335
|
+
router.get('/sessions/active', getActiveSessions);
|
|
336
|
+
// debugging / observability
|
|
337
|
+
router.get('/logs/requests', getRequestLogs);
|
|
338
|
+
// node related routes
|
|
339
|
+
router.get('/node', getNodes);
|
|
340
|
+
router.get('/node/status', nodeAdbStatusOnThisHost);
|
|
341
|
+
router.get('/node/:host/status', lodash_1.default.curry(nodeAdbStatusOnOtherHost)(pluginArgs.bindHostOrIp));
|
|
342
|
+
// node status
|
|
343
|
+
router.get('/status', (request, response) => {
|
|
344
|
+
response.json({
|
|
345
|
+
status: 'ok',
|
|
346
|
+
version: process.env.npm_package_version || 'unknown (not running from npm package)',
|
|
347
|
+
});
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
exports.default = {
|
|
351
|
+
register,
|
|
352
|
+
};
|