@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.
Files changed (228) hide show
  1. package/README.md +446 -0
  2. package/lib/package.json +207 -0
  3. package/lib/public/assets/Layouts-7IT8aFLI.js +11 -0
  4. package/lib/public/assets/Layouts-DPMls9vh.css +1 -0
  5. package/lib/public/assets/ai-settings-BbnfgdEx.js +11 -0
  6. package/lib/public/assets/apps-CRMrI4_p.js +16 -0
  7. package/lib/public/assets/apps-CcM77dgg.css +1 -0
  8. package/lib/public/assets/badge-B1nKs8zj.css +1 -0
  9. package/lib/public/assets/badge-CSvl5xIU.js +11 -0
  10. package/lib/public/assets/button-CJlKn4PZ.css +1 -0
  11. package/lib/public/assets/button-CvLaGFYj.js +26 -0
  12. package/lib/public/assets/calendar-6w-D6Oaw.js +6 -0
  13. package/lib/public/assets/clock-DcdeWBPr.js +6 -0
  14. package/lib/public/assets/cpu-DiSoXT9n.js +6 -0
  15. package/lib/public/assets/device-explorer-CajM63OJ.js +193 -0
  16. package/lib/public/assets/device-explorer-CxdUAoTL.css +1 -0
  17. package/lib/public/assets/index-ByQwMN5T.js +174 -0
  18. package/lib/public/assets/index-C1DBaoSh.js +1 -0
  19. package/lib/public/assets/index-qzCez_kk.css +1 -0
  20. package/lib/public/assets/lock-B23ibZmo.js +6 -0
  21. package/lib/public/assets/maintenance-settings-CirzA6yG.js +6 -0
  22. package/lib/public/assets/mouse-pointer-2-Cz76SHFb.js +6 -0
  23. package/lib/public/assets/plus-BBwlIevt.js +6 -0
  24. package/lib/public/assets/session-dashboard-C2k7FFv_.css +1 -0
  25. package/lib/public/assets/session-dashboard-HPDtwPOZ.js +62 -0
  26. package/lib/public/assets/settings-DrZsZwdc.js +1 -0
  27. package/lib/public/assets/trash-2-DQpvzJec.js +6 -0
  28. package/lib/public/assets/useSocket-Dxsqae2a.js +16 -0
  29. package/lib/public/assets/webhook-settings-CDPgsgkb.css +1 -0
  30. package/lib/public/assets/webhook-settings-Cp-B4Nrw.js +1 -0
  31. package/lib/public/assets/zap-DovP6iow.js +6 -0
  32. package/lib/public/favicon.ico +0 -0
  33. package/lib/public/favicon.png +0 -0
  34. package/lib/public/favicon.svg +9 -0
  35. package/lib/public/index.html +46 -0
  36. package/lib/public/logo.svg +17 -0
  37. package/lib/public/logo192.png +0 -0
  38. package/lib/public/logo512.png +0 -0
  39. package/lib/public/manifest.json +25 -0
  40. package/lib/public/robots.txt +3 -0
  41. package/lib/schema.json +348 -0
  42. package/lib/src/InternalHttpClient.js +212 -0
  43. package/lib/src/PluginContext.js +29 -0
  44. package/lib/src/XenonCapabilityManager.js +199 -0
  45. package/lib/src/app/index.js +167 -0
  46. package/lib/src/app/routers/apps.js +79 -0
  47. package/lib/src/app/routers/config.js +131 -0
  48. package/lib/src/app/routers/control.js +835 -0
  49. package/lib/src/app/routers/dashboard.js +301 -0
  50. package/lib/src/app/routers/grid.js +352 -0
  51. package/lib/src/app/routers/reservation.js +190 -0
  52. package/lib/src/app/routers/webhook.js +83 -0
  53. package/lib/src/app/swagger-docs.js +203 -0
  54. package/lib/src/app/swagger.js +366 -0
  55. package/lib/src/chromeUtils.js +148 -0
  56. package/lib/src/commands/handle.js +19 -0
  57. package/lib/src/commands/index.js +8 -0
  58. package/lib/src/config.js +73 -0
  59. package/lib/src/dashboard/asset-manager.js +84 -0
  60. package/lib/src/dashboard/commands.js +284 -0
  61. package/lib/src/dashboard/event-manager.js +699 -0
  62. package/lib/src/dashboard/services/app-service.js +134 -0
  63. package/lib/src/dashboard/services/failure-analysis-service.js +173 -0
  64. package/lib/src/dashboard/services/session-service.js +113 -0
  65. package/lib/src/data-service/CircuitBreaker.js +83 -0
  66. package/lib/src/data-service/config-service.js +155 -0
  67. package/lib/src/data-service/db.js +122 -0
  68. package/lib/src/data-service/device-service.js +320 -0
  69. package/lib/src/data-service/device-store.interface.js +2 -0
  70. package/lib/src/data-service/device-store.js +345 -0
  71. package/lib/src/data-service/pending-sessions-service.js +25 -0
  72. package/lib/src/data-service/pluginArgs.js +25 -0
  73. package/lib/src/data-service/prisma-service.js +31 -0
  74. package/lib/src/data-service/prisma-store.js +385 -0
  75. package/lib/src/data-service/queue-service.js +150 -0
  76. package/lib/src/data-service/web-config-service.js +130 -0
  77. package/lib/src/device-managers/AndroidDeviceManager.js +1155 -0
  78. package/lib/src/device-managers/ChromeDriverManager.js +68 -0
  79. package/lib/src/device-managers/HealthMonitorService.js +325 -0
  80. package/lib/src/device-managers/IOSDeviceManager.js +351 -0
  81. package/lib/src/device-managers/NodeDevices.js +82 -0
  82. package/lib/src/device-managers/android/AndroidStreamService.js +370 -0
  83. package/lib/src/device-managers/android/DeviceLockManager.js +45 -0
  84. package/lib/src/device-managers/cloud/CapabilityManager.js +26 -0
  85. package/lib/src/device-managers/cloud/Devices.js +86 -0
  86. package/lib/src/device-managers/iOSTracker.js +44 -0
  87. package/lib/src/device-managers/index.js +89 -0
  88. package/lib/src/device-managers/ios/IOSDiscoveryService.js +268 -0
  89. package/lib/src/device-managers/ios/IOSStreamService.js +893 -0
  90. package/lib/src/device-managers/ios/WDAClient.js +866 -0
  91. package/lib/src/device-utils.js +663 -0
  92. package/lib/src/enums/Capabilities.js +8 -0
  93. package/lib/src/enums/Cloud.js +11 -0
  94. package/lib/src/enums/Platform.js +9 -0
  95. package/lib/src/enums/SessionType.js +9 -0
  96. package/lib/src/enums/SocketEvents.js +15 -0
  97. package/lib/src/helpers/UniversalMjpegProxy.js +273 -0
  98. package/lib/src/helpers/index.js +229 -0
  99. package/lib/src/index.js +95 -0
  100. package/lib/src/interceptors/CommandInterceptor.js +524 -0
  101. package/lib/src/interfaces/ICloudManager.js +2 -0
  102. package/lib/src/interfaces/IDevice.js +2 -0
  103. package/lib/src/interfaces/IDeviceFilterOptions.js +2 -0
  104. package/lib/src/interfaces/IDeviceManager.js +2 -0
  105. package/lib/src/interfaces/IOptions.js +2 -0
  106. package/lib/src/interfaces/IPluginArgs.js +55 -0
  107. package/lib/src/interfaces/ISessionCapability.js +2 -0
  108. package/lib/src/logger.js +225 -0
  109. package/lib/src/plugin.js +244 -0
  110. package/lib/src/prisma.js +12 -0
  111. package/lib/src/profiling/AndroidAppProfiler.js +213 -0
  112. package/lib/src/proxy/wd-command-proxy.js +221 -0
  113. package/lib/src/scripts/generate-database-migration.js +59 -0
  114. package/lib/src/scripts/initialize-database.js +55 -0
  115. package/lib/src/scripts/install-go-ios.js +66 -0
  116. package/lib/src/scripts/prepare-prisma.js +89 -0
  117. package/lib/src/services/AICommandService.js +143 -0
  118. package/lib/src/services/AIService.js +466 -0
  119. package/lib/src/services/CleanupService.js +141 -0
  120. package/lib/src/services/EventBus.js +74 -0
  121. package/lib/src/services/InspectorService.js +395 -0
  122. package/lib/src/services/MetricsService.js +134 -0
  123. package/lib/src/services/NetworkConditioningService.js +173 -0
  124. package/lib/src/services/NotificationService.js +163 -0
  125. package/lib/src/services/RequestLogService.js +252 -0
  126. package/lib/src/services/ResourceIsolationService.js +122 -0
  127. package/lib/src/services/SecurityService.js +120 -0
  128. package/lib/src/services/ServerManager.js +284 -0
  129. package/lib/src/services/SessionHeartbeatService.js +158 -0
  130. package/lib/src/services/SessionLifecycleService.js +572 -0
  131. package/lib/src/services/SocketClient.js +71 -0
  132. package/lib/src/services/SocketServer.js +87 -0
  133. package/lib/src/services/TracingService.js +132 -0
  134. package/lib/src/services/VideoPipelineService.js +220 -0
  135. package/lib/src/services/healing/FuzzyXmlHealingProvider.js +333 -0
  136. package/lib/src/services/healing/HealEtalonService.js +98 -0
  137. package/lib/src/services/healing/HealedLocatorGenerator.js +132 -0
  138. package/lib/src/services/healing/HealingOrchestrator.js +165 -0
  139. package/lib/src/services/healing/LlmHealingProvider.js +77 -0
  140. package/lib/src/services/healing/OcrHealingProvider.js +119 -0
  141. package/lib/src/services/healing/ResilioTreeHealingProvider.js +100 -0
  142. package/lib/src/services/healing/VisualAiHealingProvider.js +90 -0
  143. package/lib/src/services/healing/types.js +12 -0
  144. package/lib/src/services/omni-vision/OmniVisionService.js +718 -0
  145. package/lib/src/services/omni-vision/VisionAssertionService.js +68 -0
  146. package/lib/src/sessions/CloudSession.js +42 -0
  147. package/lib/src/sessions/LocalSession.js +313 -0
  148. package/lib/src/sessions/RemoteSession.js +287 -0
  149. package/lib/src/sessions/SessionManager.js +238 -0
  150. package/lib/src/sessions/XenonSession.js +44 -0
  151. package/lib/src/types/CLIArgs.js +2 -0
  152. package/lib/src/types/CloudArgs.js +2 -0
  153. package/lib/src/types/CloudSchema.js +131 -0
  154. package/lib/src/types/DeviceType.js +2 -0
  155. package/lib/src/types/DeviceUpdate.js +2 -0
  156. package/lib/src/types/IOSDevice.js +2 -0
  157. package/lib/src/types/Platform.js +2 -0
  158. package/lib/src/types/SessionStatus.js +11 -0
  159. package/lib/src/validators/CapabilityValidator.js +93 -0
  160. package/lib/test/e2e/android/conf.spec.js +43 -0
  161. package/lib/test/e2e/android/conf2.spec.js +44 -0
  162. package/lib/test/e2e/android/conf3.spec.js +44 -0
  163. package/lib/test/e2e/e2ehelper.js +113 -0
  164. package/lib/test/e2e/hubnode/forward-request.spec.js +224 -0
  165. package/lib/test/e2e/hubnode/hubnode.spec.js +214 -0
  166. package/lib/test/e2e/ios/conf1.spec.js +39 -0
  167. package/lib/test/e2e/ios/conf2.spec.js +39 -0
  168. package/lib/test/e2e/plugin-harness.js +236 -0
  169. package/lib/test/e2e/plugin.spec.js +97 -0
  170. package/lib/test/e2e/telemetry_verification.spec.js +83 -0
  171. package/lib/test/e2e/video-recording-test.spec.js +63 -0
  172. package/lib/test/helpers/test-container.js +112 -0
  173. package/lib/test/integration/androidDevices.spec.js +137 -0
  174. package/lib/test/integration/cliArgs.js +73 -0
  175. package/lib/test/integration/ios/01iOSSimulator.spec.js +291 -0
  176. package/lib/test/integration/ios/02iOSDevices.spec.js +75 -0
  177. package/lib/test/integration/testHelpers.js +74 -0
  178. package/lib/test/unit/AndroidDeviceManager.spec.js +178 -0
  179. package/lib/test/unit/ChromeDriverManager.spec.js +26 -0
  180. package/lib/test/unit/CleanupService.spec.js +21 -0
  181. package/lib/test/unit/DeviceModel.spec.js +157 -0
  182. package/lib/test/unit/FuzzyXmlHealingProvider.test.js +294 -0
  183. package/lib/test/unit/GetAdbOriginal.js +42 -0
  184. package/lib/test/unit/HealingCascade.test.js +128 -0
  185. package/lib/test/unit/IOSDeviceManager.spec.js +261 -0
  186. package/lib/test/unit/RemoteIOs.spec.js +78 -0
  187. package/lib/test/unit/ResilioTreeHealingProvider.test.js +96 -0
  188. package/lib/test/unit/commands.spec.js +27 -0
  189. package/lib/test/unit/config.spec.js +27 -0
  190. package/lib/test/unit/device-service.spec.js +307 -0
  191. package/lib/test/unit/device-utils.spec.js +313 -0
  192. package/lib/test/unit/fixtures/device.config.js +4 -0
  193. package/lib/test/unit/fixtures/devices.js +89 -0
  194. package/lib/test/unit/helpers.spec.js +62 -0
  195. package/lib/test/unit/omni-vision.spec.js +100 -0
  196. package/lib/test/unit/plugin.spec.js +133 -0
  197. package/lib/tsconfig.tsbuildinfo +1 -0
  198. package/package.json +207 -0
  199. package/prisma/data.db +0 -0
  200. package/prisma/dev.db +0 -0
  201. package/prisma/dev.db-journal +0 -0
  202. package/prisma/migrations/20231011074725_initial_tables/migration.sql +47 -0
  203. package/prisma/migrations/20231226115334_update_session_log/migration.sql +2 -0
  204. package/prisma/migrations/20251204113710_add_video_recording_enabled/migration.sql +29 -0
  205. package/prisma/migrations/20251204132449_add_log_table/migration.sql +11 -0
  206. package/prisma/migrations/20251205050111_add_profiling_support/migration.sql +47 -0
  207. package/prisma/migrations/20251205050947_add_is_error_field/migration.sql +24 -0
  208. package/prisma/migrations/20260126201337_add_app_model/migration.sql +18 -0
  209. package/prisma/migrations/20260130115722_add_performance_trace_and_xenon_sync/migration.sql +2 -0
  210. package/prisma/migrations/20260130135114_add_device_models/migration.sql +57 -0
  211. package/prisma/migrations/20260130140655_make_systemport_optional/migration.sql +45 -0
  212. package/prisma/migrations/20260130140932_make_device_fields_optional/migration.sql +45 -0
  213. package/prisma/migrations/20260130141040_final_schema_fix/migration.sql +45 -0
  214. package/prisma/migrations/20260130143234_add_device_health_fields/migration.sql +4 -0
  215. package/prisma/migrations/20260130144921_add_failure_category/migration.sql +2 -0
  216. package/prisma/migrations/20260131151456_add_webhook_config/migration.sql +10 -0
  217. package/prisma/migrations/20260201094507_add_device_tags/migration.sql +11 -0
  218. package/prisma/migrations/20260201103410_add_managed_process/migration.sql +15 -0
  219. package/prisma/migrations/20260201140637_add_web_config/migration.sql +22 -0
  220. package/prisma/migrations/20260201162232_add_session_progress/migration.sql +2 -0
  221. package/prisma/migrations/20260201174231_add_total_healed_count/migration.sql +2 -0
  222. package/prisma/migrations/migration_lock.toml +3 -0
  223. package/prisma/schema.prisma +210 -0
  224. package/schema.json +348 -0
  225. package/scripts/build-xenon.sh +32 -0
  226. package/scripts/dev/debug-gemini.ts +44 -0
  227. package/scripts/generate-types-from-schema.js +86 -0
  228. package/scripts/install-compatible-driver.js +39 -0
@@ -0,0 +1,345 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
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.DeviceStoreFactory = void 0;
16
+ const logger_1 = __importDefault(require("../logger"));
17
+ const semver_1 = __importDefault(require("semver"));
18
+ const db_1 = require("./db");
19
+ const prisma_store_1 = require("./prisma-store");
20
+ const config_1 = require("../config");
21
+ /**
22
+ * LokiJS Implementation of Device Store (Legacy/Internal)
23
+ */
24
+ class LokiDeviceStore {
25
+ constructor() {
26
+ this.log = logger_1.default.scope('LokiStore');
27
+ }
28
+ getAllDevices() {
29
+ return __awaiter(this, void 0, void 0, function* () {
30
+ return (yield db_1.XenonDatabase.DeviceModel).chain().find().data();
31
+ });
32
+ }
33
+ getDevices(filterOptions) {
34
+ return __awaiter(this, void 0, void 0, function* () {
35
+ const basicFilter = process.env.NODE_ENV === 'test'
36
+ ? {}
37
+ : { host: { $ne: undefined }, userBlocked: { $ne: undefined } };
38
+ const allInColl = (yield db_1.XenonDatabase.DeviceModel).find(basicFilter);
39
+ const filtered = allInColl.filter((device) => {
40
+ var _a;
41
+ // Platform Filter
42
+ if (filterOptions.platform) {
43
+ const match = (device.platform || '').toLowerCase() === filterOptions.platform.toLowerCase();
44
+ // if (!match) console.error(`[LokiStore] Platform Mismatch: ${device.udid} (${device.platform} vs ${filterOptions.platform})`);
45
+ if (!match)
46
+ return false;
47
+ }
48
+ // Platform Version Filter
49
+ if (filterOptions.platformVersion) {
50
+ const coercedFilterVersion = semver_1.default.coerce(filterOptions.platformVersion);
51
+ const coercedDeviceVersion = semver_1.default.coerce(device.sdk || '');
52
+ if (!coercedFilterVersion ||
53
+ !coercedDeviceVersion ||
54
+ !semver_1.default.eq(coercedDeviceVersion, coercedFilterVersion))
55
+ return false;
56
+ }
57
+ // Name Filter
58
+ if ((_a = filterOptions.name) === null || _a === void 0 ? void 0 : _a.trim()) {
59
+ const nameRegex = new RegExp(filterOptions.name.trim(), 'i');
60
+ if (!nameRegex.test(device.name || ''))
61
+ return false;
62
+ }
63
+ // UDID Filter
64
+ if (filterOptions.udid) {
65
+ if (Array.isArray(filterOptions.udid)) {
66
+ if (filterOptions.udid.length > 0 && !filterOptions.udid.includes(device.udid))
67
+ return false;
68
+ }
69
+ else if (device.udid !== filterOptions.udid) {
70
+ return false;
71
+ }
72
+ }
73
+ // Device Type Filter
74
+ if (filterOptions.deviceType) {
75
+ if (device.deviceType !== filterOptions.deviceType)
76
+ return false;
77
+ }
78
+ // Host Filter
79
+ if (filterOptions.filterByHost) {
80
+ const hostFilter = filterOptions.filterByHost.toLowerCase();
81
+ if (!(device.host || '').toLowerCase().includes(hostFilter))
82
+ return false;
83
+ }
84
+ // Session ID Filter
85
+ if (filterOptions.session_id) {
86
+ if (device.session_id !== filterOptions.session_id)
87
+ return false;
88
+ }
89
+ // Busy / Offline / UserBlocked Filters
90
+ if (filterOptions.busy !== undefined && device.busy !== filterOptions.busy)
91
+ return false;
92
+ if (filterOptions.offline !== undefined && device.offline !== filterOptions.offline)
93
+ return false;
94
+ if (filterOptions.userBlocked !== undefined &&
95
+ device.userBlocked !== filterOptions.userBlocked)
96
+ return false;
97
+ // minSDK Filter
98
+ if (filterOptions.minSDK) {
99
+ const coercedMinSDK = semver_1.default.coerce(filterOptions.minSDK);
100
+ const coercedSDK = semver_1.default.coerce(device.sdk || '');
101
+ if (!coercedMinSDK || !coercedSDK || !semver_1.default.gte(coercedSDK, coercedMinSDK))
102
+ return false;
103
+ }
104
+ // maxSDK Filter
105
+ if (filterOptions.maxSDK) {
106
+ const coercedMaxSDK = semver_1.default.coerce(filterOptions.maxSDK);
107
+ const coercedSDK = semver_1.default.coerce(device.sdk || '');
108
+ if (!coercedMaxSDK || !coercedSDK || !semver_1.default.lte(coercedSDK, coercedMaxSDK))
109
+ return false;
110
+ }
111
+ return true;
112
+ });
113
+ return filtered.sort((a, b) => {
114
+ try {
115
+ const vA = semver_1.default.coerce(a.sdk || '0.0.0');
116
+ const vB = semver_1.default.coerce(b.sdk || '0.0.0');
117
+ if (vA && vB) {
118
+ if (semver_1.default.gt(vA, vB))
119
+ return -1;
120
+ if (semver_1.default.lt(vA, vB))
121
+ return 1;
122
+ }
123
+ }
124
+ catch (e) {
125
+ // Ignore sort errors
126
+ }
127
+ return 0;
128
+ });
129
+ });
130
+ }
131
+ updateDevice(udid, host, updateData) {
132
+ return __awaiter(this, void 0, void 0, function* () {
133
+ (yield db_1.XenonDatabase.DeviceModel)
134
+ .chain()
135
+ .find({ udid, host })
136
+ .update((device) => {
137
+ Object.assign(device, updateData);
138
+ });
139
+ });
140
+ }
141
+ updateDevices(filter, updateFn) {
142
+ return __awaiter(this, void 0, void 0, function* () {
143
+ (yield db_1.XenonDatabase.DeviceModel).chain().find(filter).update(updateFn);
144
+ });
145
+ }
146
+ addDevices(devices) {
147
+ return __awaiter(this, void 0, void 0, function* () {
148
+ const deviceModel = yield db_1.XenonDatabase.DeviceModel;
149
+ const added = [];
150
+ for (const device of devices) {
151
+ const existing = deviceModel.findOne({ udid: device.udid, host: device.host });
152
+ if (!existing) {
153
+ const cleanDevice = Object.assign({}, device);
154
+ if (cleanDevice.host === undefined)
155
+ cleanDevice.host = 'Local';
156
+ if (cleanDevice.userBlocked === undefined)
157
+ cleanDevice.userBlocked = false;
158
+ if (cleanDevice.busy === undefined)
159
+ cleanDevice.busy = false;
160
+ if (cleanDevice.offline === undefined)
161
+ cleanDevice.offline = false;
162
+ // @ts-ignore - LokiJS adds $loki metadata that we need to strip before insert
163
+ delete cleanDevice['$loki'];
164
+ // @ts-ignore
165
+ delete cleanDevice['meta'];
166
+ deviceModel.insert(cleanDevice);
167
+ added.push(cleanDevice);
168
+ }
169
+ }
170
+ return added;
171
+ });
172
+ }
173
+ removeDevices(filter) {
174
+ return __awaiter(this, void 0, void 0, function* () {
175
+ (yield db_1.XenonDatabase.DeviceModel).chain().find(filter).remove();
176
+ });
177
+ }
178
+ clearStorage() {
179
+ return __awaiter(this, void 0, void 0, function* () {
180
+ (yield db_1.XenonDatabase.DeviceModel).removeDataOnly();
181
+ });
182
+ }
183
+ findDevice(filter) {
184
+ return __awaiter(this, void 0, void 0, function* () {
185
+ return (yield db_1.XenonDatabase.DeviceModel).findOne(filter);
186
+ });
187
+ }
188
+ findDevices(filter) {
189
+ return __awaiter(this, void 0, void 0, function* () {
190
+ return (yield db_1.XenonDatabase.DeviceModel).find(filter);
191
+ });
192
+ }
193
+ findAndLockDevice(filterOptions) {
194
+ return __awaiter(this, void 0, void 0, function* () {
195
+ const devices = yield this.getDevices(filterOptions);
196
+ const available = devices.find((d) => !d.busy && !d.userBlocked);
197
+ if (available) {
198
+ yield this.updateDevice(available.udid, available.host, { busy: true });
199
+ return available;
200
+ }
201
+ return null;
202
+ });
203
+ }
204
+ resetMetrics() {
205
+ return __awaiter(this, void 0, void 0, function* () {
206
+ (yield db_1.XenonDatabase.DeviceModel)
207
+ .chain()
208
+ .find()
209
+ .update((device) => {
210
+ device.totalHealedCount = 0;
211
+ });
212
+ });
213
+ }
214
+ }
215
+ class LokiPendingSessionStore {
216
+ addPendingSession(capability) {
217
+ return __awaiter(this, void 0, void 0, function* () {
218
+ (yield db_1.XenonDatabase.PendingSessionsModel).insert(capability);
219
+ });
220
+ }
221
+ removePendingSession(sessionCapabilityId) {
222
+ return __awaiter(this, void 0, void 0, function* () {
223
+ (yield db_1.XenonDatabase.PendingSessionsModel)
224
+ .chain()
225
+ .find({ capability_id: sessionCapabilityId })
226
+ .remove();
227
+ });
228
+ }
229
+ getAllPendingSessions() {
230
+ return __awaiter(this, void 0, void 0, function* () {
231
+ return (yield db_1.XenonDatabase.PendingSessionsModel).chain().find().data();
232
+ });
233
+ }
234
+ remove(session) {
235
+ return __awaiter(this, void 0, void 0, function* () {
236
+ (yield db_1.XenonDatabase.PendingSessionsModel).remove(session);
237
+ });
238
+ }
239
+ }
240
+ class LokiCLIArgsStore {
241
+ addCLIArgs(args) {
242
+ return __awaiter(this, void 0, void 0, function* () {
243
+ (yield db_1.XenonDatabase.CLIArgs).insert(args);
244
+ });
245
+ }
246
+ getCLIArgs() {
247
+ return __awaiter(this, void 0, void 0, function* () {
248
+ return (yield db_1.XenonDatabase.CLIArgs).chain().find().data();
249
+ });
250
+ }
251
+ }
252
+ class LokiHealEtalonStore {
253
+ constructor() {
254
+ this.collectionName = 'locator-etalons';
255
+ }
256
+ getCollection() {
257
+ return __awaiter(this, void 0, void 0, function* () {
258
+ const db = yield db_1.XenonDatabase.db;
259
+ let coll = db.getCollection(this.collectionName);
260
+ if (!coll) {
261
+ coll = db.addCollection(this.collectionName, { unique: ['selector'] });
262
+ }
263
+ return coll;
264
+ });
265
+ }
266
+ saveSignature(etalon) {
267
+ return __awaiter(this, void 0, void 0, function* () {
268
+ const coll = yield this.getCollection();
269
+ const existing = coll.findOne({ selector: etalon.selector });
270
+ if (existing) {
271
+ Object.assign(existing, etalon);
272
+ coll.update(existing);
273
+ }
274
+ else {
275
+ coll.insert(etalon);
276
+ }
277
+ });
278
+ }
279
+ getSignature(selector) {
280
+ return __awaiter(this, void 0, void 0, function* () {
281
+ const coll = yield this.getCollection();
282
+ return coll.findOne({ selector });
283
+ });
284
+ }
285
+ }
286
+ /**
287
+ * Factory for Device Store.
288
+ * Determines storage type based on config.
289
+ */
290
+ class DeviceStoreFactory {
291
+ static getStorageType() {
292
+ if (process.env.NODE_ENV === 'test')
293
+ return 'loki';
294
+ const type = process.env.XENON_STORAGE_TYPE || config_1.config.databaseProvider;
295
+ if (type === 'sqlite' || type === 'postgresql' || type === 'prisma')
296
+ return 'prisma';
297
+ return 'loki';
298
+ }
299
+ static getStore() {
300
+ if (!this._deviceStore) {
301
+ if (this.getStorageType() === 'prisma') {
302
+ this._deviceStore = new prisma_store_1.PrismaDeviceStore();
303
+ }
304
+ else {
305
+ this._deviceStore = new LokiDeviceStore();
306
+ }
307
+ }
308
+ return this._deviceStore;
309
+ }
310
+ static getPendingSessionStore() {
311
+ if (!this._pendingSessionStore) {
312
+ if (this.getStorageType() === 'prisma') {
313
+ this._pendingSessionStore = new prisma_store_1.PrismaPendingSessionStore();
314
+ }
315
+ else {
316
+ this._pendingSessionStore = new LokiPendingSessionStore();
317
+ }
318
+ }
319
+ return this._pendingSessionStore;
320
+ }
321
+ static getCLIArgsStore() {
322
+ if (!this._cliArgsStore) {
323
+ if (this.getStorageType() === 'prisma') {
324
+ this._cliArgsStore = new prisma_store_1.PrismaCLIArgsStore();
325
+ }
326
+ else {
327
+ this._cliArgsStore = new LokiCLIArgsStore();
328
+ }
329
+ }
330
+ return this._cliArgsStore;
331
+ }
332
+ static getHealEtalonStore() {
333
+ if (!this._healEtalonStore) {
334
+ if (this.getStorageType() === 'prisma') {
335
+ const { PrismaHealEtalonStore } = require('./prisma-store');
336
+ this._healEtalonStore = new PrismaHealEtalonStore();
337
+ }
338
+ else {
339
+ this._healEtalonStore = new LokiHealEtalonStore();
340
+ }
341
+ }
342
+ return this._healEtalonStore;
343
+ }
344
+ }
345
+ exports.DeviceStoreFactory = DeviceStoreFactory;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.addNewPendingSession = addNewPendingSession;
13
+ exports.removePendingSession = removePendingSession;
14
+ const device_store_1 = require("./device-store");
15
+ const store = device_store_1.DeviceStoreFactory.getPendingSessionStore();
16
+ function addNewPendingSession(capability) {
17
+ return __awaiter(this, void 0, void 0, function* () {
18
+ yield store.addPendingSession(capability);
19
+ });
20
+ }
21
+ function removePendingSession(sessionCapabilityId) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ yield store.removePendingSession(sessionCapabilityId);
24
+ });
25
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.addCLIArgs = addCLIArgs;
13
+ exports.getCLIArgs = getCLIArgs;
14
+ const device_store_1 = require("./device-store");
15
+ const store = device_store_1.DeviceStoreFactory.getCLIArgsStore();
16
+ function addCLIArgs(args) {
17
+ return __awaiter(this, void 0, void 0, function* () {
18
+ yield store.addCLIArgs(args);
19
+ });
20
+ }
21
+ function getCLIArgs() {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ return yield store.getCLIArgs();
24
+ });
25
+ }
@@ -0,0 +1,31 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PrismaService = void 0;
13
+ const client_1 = require("@prisma/client");
14
+ const config_1 = require("../config");
15
+ const typedi_1 = require("typedi");
16
+ let PrismaService = class PrismaService extends client_1.PrismaClient {
17
+ constructor() {
18
+ super({
19
+ datasources: {
20
+ db: {
21
+ url: config_1.config.databaseUrl,
22
+ },
23
+ },
24
+ });
25
+ }
26
+ };
27
+ exports.PrismaService = PrismaService;
28
+ exports.PrismaService = PrismaService = __decorate([
29
+ (0, typedi_1.Service)(),
30
+ __metadata("design:paramtypes", [])
31
+ ], PrismaService);