@xenon-device-management/xenon 2.14.0 → 2.16.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 +44 -29
- package/lib/package.json +6 -5
- package/lib/public/assets/{AnnotationOverlay-B_VNtKBH.js → AnnotationOverlay-2W4JvEyZ.js} +1 -1
- package/lib/public/assets/{ApiKeyGate-BwuaMjkX.js → ApiKeyGate-GmckX_7r.js} +1 -1
- package/lib/public/assets/DeviceMosaicView-DqODzkyo.js +2 -0
- package/lib/public/assets/{EmptyState-BSjhk_IV.js → EmptyState-7hETKEWb.js} +1 -1
- package/lib/public/assets/{FieldGroup-Cb5QZsE1.js → FieldGroup-GOgssFEP.js} +1 -1
- package/lib/public/assets/{FilterMenu-BAaSlWbW.js → FilterMenu-Yvf6RGMd.js} +1 -1
- package/lib/public/assets/{Menu-JGGYrSQQ.js → Menu-KrPnfdsf.js} +1 -1
- package/lib/public/assets/{Modal-CFCp3n9d.js → Modal-C6WjZFeI.js} +1 -1
- package/lib/public/assets/{RecordingPage-CbJj_EBT.js → RecordingPage-CSRIhZEh.js} +1 -1
- package/lib/public/assets/{RecordingsPage-BJeYnygR.js → RecordingsPage-CB8ST3nE.js} +1 -1
- package/lib/public/assets/{SegmentedControl-Bg42Atjy.js → SegmentedControl-C9o90KId.js} +1 -1
- package/lib/public/assets/{SettingCard-Njz1pUIJ.js → SettingCard-CPm3w9l2.js} +1 -1
- package/lib/public/assets/{Table-BcTm5xV2.js → Table-DwIgERRt.js} +1 -1
- package/lib/public/assets/{activity-DOVdsfMQ.js → activity-DrLbHifn.js} +1 -1
- package/lib/public/assets/ai-settings-DU_Ls06P.js +16 -0
- package/lib/public/assets/{api-keys-BKnNSTw9.js → api-keys-CWYdEzJ_.js} +1 -1
- package/lib/public/assets/{apps-D0SC6uw6.js → apps-BqNVdln7.js} +1 -1
- package/lib/public/assets/{arrow-left-MMbTmgoE.js → arrow-left-BtB0_Jg_.js} +1 -1
- package/lib/public/assets/{arrow-right-BMfnGmxW.js → arrow-right-C8NhdtyN.js} +1 -1
- package/lib/public/assets/{arrow-up-right-DuAftMWB.js → arrow-up-right-gMg0ffvv.js} +1 -1
- package/lib/public/assets/{auth-shell-nZC2JNDO.js → auth-shell-CiYZ3N4M.js} +2 -2
- package/lib/public/assets/{builds-page-hDCgTwkS.js → builds-page-EaaqDmLN.js} +1 -1
- package/lib/public/assets/{button-Dda4irn_.js → button-DDau4Axv.js} +1 -1
- package/lib/public/assets/{calendar-BMr0Q62v.js → calendar-DQ83B1ed.js} +1 -1
- package/lib/public/assets/{check-CZ9iw9-e.js → check-K1ovTQam.js} +1 -1
- package/lib/public/assets/{chevron-right-BRYJJVC9.js → chevron-right-Biq00pMt.js} +1 -1
- package/lib/public/assets/{circle-check-CqAJjQ5O.js → circle-check-CBv88cH7.js} +1 -1
- package/lib/public/assets/{circle-x-DlDJtnVz.js → circle-x-Bmltailn.js} +1 -1
- package/lib/public/assets/{clock-CpuDKysU.js → clock-BPrld-3h.js} +1 -1
- package/lib/public/assets/{copy-CAQydNFe.js → copy-t0QB14JI.js} +1 -1
- package/lib/public/assets/derive-UnLRp4r3.js +1 -0
- package/lib/public/assets/device-explorer-BgGZ8AvV.js +282 -0
- package/lib/public/assets/{download-C9XG6lLv.js → download-BroHxNOh.js} +1 -1
- package/lib/public/assets/forgot-password-Bjmf49i6.js +1 -0
- package/lib/public/assets/{h264Stream-VQBphYhg.js → h264Stream-DeD__6wa.js} +6 -6
- package/lib/public/assets/{index-DJGc1M2f.js → index-72oF89LJ.js} +1 -1
- package/lib/public/assets/index-B0JeuZbg.js +15 -0
- package/lib/public/assets/index-B0gQkEg0.js +219 -0
- package/lib/public/assets/{input-Cm0tmSoc.js → input-DIc4MSC7.js} +1 -1
- package/lib/public/assets/{line-chart-D2DyJCml.js → line-chart-BcWm2vW8.js} +1 -1
- package/lib/public/assets/{list-checks-UWf1GY99.js → list-checks-B06IJJad.js} +1 -1
- package/lib/public/assets/{lock-CCJv9m_I.js → lock-pVLvnN30.js} +1 -1
- package/lib/public/assets/{login-f8vOVW-U.js → login-CN77vy--.js} +1 -1
- package/lib/public/assets/{maintenance-settings-C1PrkuAH.js → maintenance-settings-CSdzQSkY.js} +1 -1
- package/lib/public/assets/{monitor-B2jDgwm7.js → monitor-BtrN5IkI.js} +1 -1
- package/lib/public/assets/{mouse-pointer-2-DLI1RtzU.js → mouse-pointer-2-CNsQfo6w.js} +1 -1
- package/lib/public/assets/{network-ebT86qoi.js → network-BSfA8ZxG.js} +1 -1
- package/lib/public/assets/{overview-C0aykVrd.js → overview-BfTebCK5.js} +1 -1
- package/lib/public/assets/{page-header-BjzgWz-T.js → page-header-D8KUX6Qg.js} +1 -1
- package/lib/public/assets/{play-DLG9t8FU.js → play-Cvc8xzic.js} +1 -1
- package/lib/public/assets/{plus-nBFSMu_X.js → plus-C9Zj84UF.js} +1 -1
- package/lib/public/assets/{profile-page-CSl0UYlv.js → profile-page-Bi27STgs.js} +1 -1
- package/lib/public/assets/{reset-password-LeOuHqmB.js → reset-password-CPsOuwSu.js} +1 -1
- package/lib/public/assets/runbook-page-DEQ-DBOX.js +304 -0
- package/lib/public/assets/{select-88jHcl-Z.js → select-BWpnhWXj.js} +1 -1
- package/lib/public/assets/{selector-detail-redirect-BbXKJjZM.js → selector-detail-redirect-BefSCSpe.js} +1 -1
- package/lib/public/assets/{selector-health-page-B4rA1Xkv.js → selector-health-page-MSk96Zz7.js} +1 -1
- package/lib/public/assets/session-detail-page-DPyBNef_.js +4 -0
- package/lib/public/assets/{settings-Dep_3kbA.css → settings-K8UHWMdI.css} +1 -1
- package/lib/public/assets/{settings-GF6ZMSQ6.js → settings-V6x-cXwy.js} +1 -1
- package/lib/public/assets/{stat-tile-BV98e_Sv.js → stat-tile-Duex-GZD.js} +1 -1
- package/lib/public/assets/{tablet-BiAsnFDj.js → tablet-BBcoqBmL.js} +1 -1
- package/lib/public/assets/{teams-B4-jrr-1.js → teams-ts8p5rEh.js} +1 -1
- package/lib/public/assets/{trash-2-C5RSuX0e.js → trash-2-CZ2ew6AZ.js} +1 -1
- package/lib/public/assets/{upload-BG7_rMXK.js → upload-Dv99y_le.js} +1 -1
- package/lib/public/assets/{use-builds-data-J-riQYyC.js → use-builds-data-DrYC8JCF.js} +1 -1
- package/lib/public/assets/{use-password-reset-mode-C8-eH-UG.js → use-password-reset-mode-C7QkBNkP.js} +1 -1
- package/lib/public/assets/{users-CFba5TSy.js → users-D7tKMESH.js} +1 -1
- package/lib/public/assets/{users-Cp0beJm3.js → users-gJ5Y01yo.js} +1 -1
- package/lib/public/assets/{video-off-DDsEISjV.js → video-off-CqZVuZGs.js} +1 -1
- package/lib/public/assets/{webhook-settings-BGu32vSB.js → webhook-settings-DI5DSW99.js} +1 -1
- package/lib/public/assets/{zap-l4VaXzq8.js → zap-ClcHFxfo.js} +1 -1
- package/lib/public/index.html +1 -1
- package/lib/schema.json +16 -12
- package/lib/src/InternalHttpClient.js +27 -5
- package/lib/src/XenonCapabilityManager.js +10 -3
- package/lib/src/app/dashboardPluginLink.js +117 -0
- package/lib/src/app/index.js +13 -34
- package/lib/src/app/openapi/control.yaml +6 -4
- package/lib/src/app/openapi/grid.yaml +8 -2
- package/lib/src/app/openapi/identity.yaml +103 -31
- package/lib/src/app/openapi/platform.yaml +33 -15
- package/lib/src/app/openapi/sessions.yaml +12 -3
- package/lib/src/app/routers/apikeys.js +14 -2
- package/lib/src/app/routers/auth.js +31 -6
- package/lib/src/app/routers/control.js +13 -5
- package/lib/src/app/routers/dashboard.js +42 -27
- package/lib/src/app/routers/grid.js +5 -3
- package/lib/src/app/routers/profile.js +21 -0
- package/lib/src/app/routers/users.js +12 -6
- package/lib/src/app/swagger.js +2 -0
- package/lib/src/app/ws/h264StreamWs.js +10 -1
- package/lib/src/app/ws/nodeSocketRelay.js +77 -11
- package/lib/src/config.js +1 -0
- package/lib/src/dashboard/commandLogFields.js +42 -0
- package/lib/src/dashboard/commands.js +5 -5
- package/lib/src/dashboard/event-manager.js +64 -204
- package/lib/src/dashboard/services/failure-analysis-service.js +118 -105
- package/lib/src/dashboard/services/failureCategories.js +264 -0
- package/lib/src/dashboard/sessionCommandSummary.js +39 -0
- package/lib/src/data-service/device-store.js +14 -1
- package/lib/src/data-service/prisma-store.js +19 -7
- package/lib/src/data-service/web-config-service.js +7 -0
- package/lib/src/device-managers/AndroidDeviceManager.js +61 -23
- package/lib/src/device-managers/IOSDeviceManager.js +10 -0
- package/lib/src/device-managers/android/AndroidH264StreamService.js +69 -20
- package/lib/src/device-managers/android/H264Multiplexer.js +38 -4
- package/lib/src/device-utils.js +29 -3
- package/lib/src/gateway/defaultGateway.js +1 -1
- package/lib/src/gateway/forwardToNode.js +6 -11
- package/lib/src/gateway/healReport.js +87 -0
- package/lib/src/gateway/hubSessionToken.js +27 -4
- package/lib/src/gateway/nodeWebDriverUrl.js +3 -5
- package/lib/src/gateway/sessionGateway.js +12 -2
- package/lib/src/generated/client/edge.js +4 -3
- package/lib/src/generated/client/index-browser.js +1 -0
- package/lib/src/generated/client/index.d.ts +32 -0
- package/lib/src/generated/client/index.js +4 -3
- package/lib/src/generated/client/package.json +1 -1
- package/lib/src/generated/client/schema.prisma +3 -0
- package/lib/src/generated/client/wasm.js +1 -0
- package/lib/src/helpers/outboundProxy.js +219 -0
- package/lib/src/index.js +21 -0
- package/lib/src/interceptors/CommandInterceptor.js +256 -196
- package/lib/src/interceptors/xenonScripts.js +28 -7
- package/lib/src/logger.js +3 -1
- package/lib/src/middleware/authMiddleware.js +15 -3
- package/lib/src/middleware/commandCaller.js +3 -3
- package/lib/src/middleware/verifyCredential.js +58 -1
- package/lib/src/plugin.js +16 -6
- package/lib/src/scripts/database-check.js +3 -3
- package/lib/src/scripts/initialize-database.js +35 -33
- package/lib/src/scripts/run-migrations.js +1079 -27
- package/lib/src/services/AICommandService.js +9 -2
- package/lib/src/services/AIService.js +192 -42
- package/lib/src/services/ApiKeyService.js +16 -5
- package/lib/src/services/EmailService.js +29 -0
- package/lib/src/services/InterceptorService.js +6 -2
- package/lib/src/services/OrphanSweeper.js +8 -0
- package/lib/src/services/SelectorStateService.js +11 -7
- package/lib/src/services/SelectorVerificationJob.js +21 -6
- package/lib/src/services/ServerManager.js +11 -1
- package/lib/src/services/SessionLifecycleService.js +118 -44
- package/lib/src/services/SocketClient.js +11 -0
- package/lib/src/services/SocketServer.js +380 -45
- package/lib/src/services/TeamService.js +5 -1
- package/lib/src/services/TracingService.js +171 -60
- package/lib/src/services/UserService.js +14 -3
- package/lib/src/services/UserSessionService.js +16 -4
- package/lib/src/services/bug-report/video-slice.js +4 -1
- package/lib/src/services/device-access/leaseOverride.js +7 -5
- package/lib/src/services/healing/FuzzyXmlHealingProvider.js +51 -0
- package/lib/src/services/healing/HealEtalonService.js +3 -2
- package/lib/src/services/healing/HealingOrchestrator.js +57 -72
- package/lib/src/services/healing/OcrHealingProvider.js +41 -64
- package/lib/src/services/healing/ResilioTreeHealingProvider.js +41 -50
- package/lib/src/services/healing/VisualAiHealingProvider.js +1 -1
- package/lib/src/services/healing/fingerprintIdentity.js +126 -0
- package/lib/src/services/healing/resilioPath.js +274 -0
- package/lib/src/services/identity/identityChanges.js +41 -0
- package/lib/src/services/logcat/SessionDeviceLogs.js +358 -0
- package/lib/src/services/logcat/deviceLogBook.js +164 -0
- package/lib/src/services/logcat/iosDriverLog.js +178 -0
- package/lib/src/services/ocr/ocrData.js +118 -0
- package/lib/src/services/ocr/vendor/LICENSE-tessdata.txt +202 -0
- package/lib/src/services/ocr/vendor/eng.traineddata.gz +0 -0
- package/lib/src/services/omni-vision/OmniVisionService.js +83 -56
- package/lib/src/services/passwordResetLink.js +50 -9
- package/lib/src/services/passwordResetMode.js +3 -1
- package/lib/src/services/publicUrl.js +45 -0
- package/lib/src/services/selector-health/SelectorVisibilityResolver.js +121 -0
- package/lib/src/services/session/sessionIdentity.js +5 -3
- package/lib/src/services/session/shutdownReason.js +26 -0
- package/lib/src/services/settings/aiEngineSettings.js +219 -0
- package/lib/src/services/token/JwtKeyService.js +8 -2
- package/lib/src/services/token/mcpTokenTtl.js +27 -0
- package/lib/src/services/token/mintedLifetime.js +51 -0
- package/lib/src/sessions/LocalSession.js +29 -1
- package/lib/src/sessions/RemoteSession.js +12 -2
- package/lib/src/sessions/SessionManager.js +4 -1
- package/lib/src/sessions/sessionMemory.js +25 -0
- package/lib/test/helpers/driver-log.js +38 -0
- package/lib/test/helpers/fake-ai-provider.js +188 -0
- package/lib/test/helpers/fake-http-proxy.js +106 -0
- package/lib/test/helpers/loki-stores.js +33 -0
- package/lib/test/helpers/otlp-probe.js +107 -0
- package/lib/test/helpers/page-sources.js +164 -0
- package/lib/test/helpers/scratch-database.js +57 -13
- package/lib/test/integration/androidDevices.spec.js +1 -1
- package/lib/test/integration/audit-ingest.spec.js +10 -10
- package/lib/test/integration/auth-flow.spec.js +9 -14
- package/lib/test/integration/auth-rate-limit.spec.js +6 -3
- package/lib/test/integration/bug-report-route.spec.js +22 -2
- package/lib/test/integration/forgot-password-rate-limit.spec.js +6 -3
- package/lib/test/integration/forgot-password.spec.js +17 -18
- package/lib/test/integration/ios/01iOSSimulator.spec.js +1 -1
- package/lib/test/integration/ios/02iOSDevices.spec.js +1 -1
- package/lib/test/integration/legacy-deprecation-headers.spec.js +5 -2
- package/lib/test/integration/migration.spec.js +6 -1
- package/lib/test/integration/node-pair-auth-rest.spec.js +5 -9
- package/lib/test/integration/ports-router.spec.js +4 -4
- package/lib/test/integration/prisma-device-store-add-devices.spec.js +2 -3
- package/lib/test/integration/prisma-device-store-team-filter.spec.js +2 -5
- package/lib/test/integration/profile-tokens.spec.js +10 -16
- package/lib/test/integration/recordings-router.spec.js +16 -16
- package/lib/test/integration/reset-revokes-sessions.spec.js +4 -9
- package/lib/test/integration/role-matrix.spec.js +4 -9
- package/lib/test/integration/sdk-leases-router.spec.js +9 -9
- package/lib/test/integration/sdk-version.spec.js +2 -2
- package/lib/test/integration/selector-health-endpoint.spec.js +5 -5
- package/lib/test/integration/selector-state-flow.spec.js +5 -5
- package/lib/test/integration/team-membership-migration.spec.js +73 -12
- package/lib/test/integration/team-visibility-apps.spec.js +15 -22
- package/lib/test/integration/team-visibility-control.spec.js +96 -69
- package/lib/test/integration/team-visibility-dashboard.spec.js +7 -23
- package/lib/test/integration/team-visibility-grid.spec.js +16 -15
- package/lib/test/integration/team-visibility-leases.spec.js +8 -11
- package/lib/test/integration/team-visibility-recordings.spec.js +6 -19
- package/lib/test/integration/team-visibility-sessions.spec.js +6 -19
- package/lib/test/integration/users-flow.spec.js +7 -12
- package/lib/test/integration/users-lockout.spec.js +5 -3
- package/lib/test/unit/EmailService.test.js +66 -0
- package/lib/test/unit/ResilioTreeHealingProvider.test.js +46 -19
- package/lib/test/unit/XenonCapabilityManager.spec.js +23 -0
- package/lib/test/unit/ai-call-time-limit.spec.js +130 -0
- package/lib/test/unit/ai-engine-settings.spec.js +338 -0
- package/lib/test/unit/ai-provider-switch.spec.js +130 -0
- package/lib/test/unit/ai-rate-limit.spec.js +126 -0
- package/lib/test/unit/android-adb-retry.spec.js +112 -0
- package/lib/test/unit/android-h264-viewers.spec.js +272 -0
- package/lib/test/unit/android-preview-hold.spec.js +3 -2
- package/lib/test/unit/apikeys-router.spec.js +84 -0
- package/lib/test/unit/authMiddleware.bearer.spec.js +9 -0
- package/lib/test/unit/authMiddleware.credentialLifetime.spec.js +149 -0
- package/lib/test/unit/bug-report/video-slice.spec.js +19 -0
- package/lib/test/unit/command-log-network-capture.spec.js +191 -0
- package/lib/test/unit/dashboard-events-device-logs.spec.js +255 -0
- package/lib/test/unit/dashboard-events-team-scope.spec.js +6 -3
- package/lib/test/unit/dashboard-plugin-link.spec.js +213 -0
- package/lib/test/unit/database-check.spec.js +1 -0
- package/lib/test/unit/device-log-book.spec.js +180 -0
- package/lib/test/unit/device-utils.spec.js +13 -4
- package/lib/test/unit/enable-dashboard-option.spec.js +57 -0
- package/lib/test/unit/event-log-session-data.spec.js +251 -0
- package/lib/test/unit/failure-analysis.spec.js +196 -0
- package/lib/test/unit/failure-categories.spec.js +130 -0
- package/lib/test/unit/failure-categorization.spec.js +393 -0
- package/lib/test/unit/fingerprint-identity.spec.js +433 -0
- package/lib/test/unit/h264-multiplexer.spec.js +46 -0
- package/lib/test/unit/heal-report.spec.js +71 -0
- package/lib/test/unit/healing-instrumentation.spec.js +6 -1
- package/lib/test/unit/healing-tier-gate.spec.js +74 -29
- package/lib/test/unit/healing-tiers-every-session.spec.js +219 -0
- package/lib/test/unit/hub-node-gateway-appium-server.spec.js +243 -1
- package/lib/test/unit/interceptor-visual-elements.spec.js +192 -0
- package/lib/test/unit/ios-driver-log.spec.js +168 -0
- package/lib/test/unit/ios-simulator-session-readiness.spec.js +187 -0
- package/lib/test/unit/ios-simulator-session-teardown.spec.js +158 -0
- package/lib/test/unit/lease/lease-override.spec.js +23 -6
- package/lib/test/unit/lease/session-lease-proof.spec.js +16 -4
- package/lib/test/unit/logcat-ws.spec.js +78 -37
- package/lib/test/unit/logger-json-levels.spec.js +44 -0
- package/lib/test/unit/mcp-token-ttl.spec.js +38 -0
- package/lib/test/unit/observability-example-loki.spec.js +25 -0
- package/lib/test/unit/ocr-healing-tier-real-ocr.spec.js +113 -0
- package/lib/test/unit/ocr-healing-tier.spec.js +122 -0
- package/lib/test/unit/ocr-offline.spec.js +213 -0
- package/lib/test/unit/omni-virtual-element-store.spec.js +301 -0
- package/lib/test/unit/omni-vision-ios-points.spec.js +0 -2
- package/lib/test/unit/omni-vision.spec.js +5 -7
- package/lib/test/unit/openapi-for-site.spec.js +80 -0
- package/lib/test/unit/outbound-proxy.spec.js +320 -0
- package/lib/test/unit/package-engines.spec.js +27 -0
- package/lib/test/unit/passwordResetMode.test.js +10 -2
- package/lib/test/unit/port-exhaustion.spec.js +2 -1
- package/lib/test/unit/profile-router.test.js +122 -1
- package/lib/test/unit/proxy-option.spec.js +358 -0
- package/lib/test/unit/queue-requester.spec.js +1 -1
- package/lib/test/unit/reset-link-address.spec.js +266 -0
- package/lib/test/unit/reset-link.test.js +10 -4
- package/lib/test/unit/resilio-path-healing.spec.js +270 -0
- package/lib/test/unit/run-migrations-database.spec.js +807 -0
- package/lib/test/unit/run-migrations-fail-fast.test.js +41 -27
- package/lib/test/unit/run-migrations.test.js +864 -0
- package/lib/test/unit/selector-health-actions.spec.js +3 -1
- package/lib/test/unit/selector-learning-every-session.spec.js +179 -0
- package/lib/test/unit/selector-state-service.spec.js +72 -23
- package/lib/test/unit/selector-verification-clean-build.spec.js +130 -0
- package/lib/test/unit/selector-verification-job.spec.js +28 -19
- package/lib/test/unit/selector-verification-missed-regression.spec.js +2 -2
- package/lib/test/unit/selector-visibility-resolver.spec.js +209 -0
- package/lib/test/unit/self-healing-boot.spec.js +10 -5
- package/lib/test/unit/self-healing-setting.spec.js +7 -6
- package/lib/test/unit/session-app-resolution.spec.js +5 -1
- package/lib/test/unit/session-attribution-wiring.spec.js +41 -13
- package/lib/test/unit/session-create-credential-owner.spec.js +242 -0
- package/lib/test/unit/session-credential-strip.spec.js +1 -1
- package/lib/test/unit/session-device-logs-ios.spec.js +180 -0
- package/lib/test/unit/session-device-logs.spec.js +356 -0
- package/lib/test/unit/session-end-failure-analysis.spec.js +133 -0
- package/lib/test/unit/session-log-indexes.spec.js +64 -3
- package/lib/test/unit/socket-team-scope.integration.spec.js +749 -0
- package/lib/test/unit/socketServer.scopedEmit.spec.js +237 -5
- package/lib/test/unit/socketServer.sessionCookie.spec.js +2 -1
- package/lib/test/unit/stream-start-pipelines.spec.js +72 -18
- package/lib/test/unit/token-mint-limits.spec.js +165 -0
- package/lib/test/unit/tracing-export-routing.spec.js +137 -0
- package/lib/test/unit/tracing-session-spans.spec.js +337 -0
- package/lib/test/unit/unexpected-shutdown-reason.spec.js +163 -0
- package/lib/test/unit/verify-credential.spec.js +33 -0
- package/lib/test/unit/vision-assertion.spec.js +3 -2
- package/lib/test/unit/web-config-service.spec.js +19 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -5
- package/prisma/migrations/20261004174413_locator_etalon_path/migration.sql +2 -0
- package/prisma/schema.prisma +3 -0
- package/schema.json +16 -12
- package/scripts/dev/readme-screenshots.js +276 -23
- package/scripts/dev/screenshot-fixtures/logcat.js +157 -0
- package/scripts/dev/screenshot-fixtures/phone-screen.html +469 -0
- package/scripts/dev/screenshot-fixtures/session.js +242 -0
- package/scripts/export-openapi.js +32 -0
- package/scripts/lib/openapi-for-site.js +79 -0
- package/lib/public/assets/BugReportButton-BAt0_pzq.js +0 -15
- package/lib/public/assets/DeviceMosaicView-BYaQHhTf.js +0 -2
- package/lib/public/assets/ai-settings-CsuJroRf.js +0 -21
- package/lib/public/assets/device-explorer-CdO6_nrn.js +0 -282
- package/lib/public/assets/forgot-password-CGnkRgE9.js +0 -1
- package/lib/public/assets/index-BbKEXUFH.js +0 -219
- package/lib/public/assets/runbook-page-CMMeQml9.js +0 -124
- package/lib/public/assets/session-detail-page-COL_RZxw.js +0 -4
- package/lib/src/scripts/prepare-prisma.js +0 -89
- /package/lib/public/assets/{BugReportButton-CPBjfiv4.css → index-CPBjfiv4.css} +0 -0
|
@@ -307,6 +307,9 @@ model LocatorEtalon {
|
|
|
307
307
|
strategy String
|
|
308
308
|
attributes String
|
|
309
309
|
nodeName String
|
|
310
|
+
/// The element's path through the page source when the selector last
|
|
311
|
+
/// worked (JSON, resilioPath.ts), for the Resilio healing tier.
|
|
312
|
+
path String?
|
|
310
313
|
lastSeen DateTime @default(now())
|
|
311
314
|
createdAt DateTime @default(now())
|
|
312
315
|
updatedAt DateTime @updatedAt
|
|
@@ -0,0 +1,219 @@
|
|
|
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.outboundProxyFor = outboundProxyFor;
|
|
16
|
+
exports.envProxyFor = envProxyFor;
|
|
17
|
+
exports.proxyAgentFor = proxyAgentFor;
|
|
18
|
+
exports.socketProxyAgentFor = socketProxyAgentFor;
|
|
19
|
+
exports.axiosProxyConfig = axiosProxyConfig;
|
|
20
|
+
const typedi_1 = require("typedi");
|
|
21
|
+
const http_proxy_agent_1 = require("http-proxy-agent");
|
|
22
|
+
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
23
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
24
|
+
const PluginContext_1 = require("../PluginContext");
|
|
25
|
+
/**
|
|
26
|
+
* The proxy for one of Xenon's own calls to another server (a hub's to its
|
|
27
|
+
* nodes and to a cloud provider, a node's to its hub, and the rest of
|
|
28
|
+
* Xenon's internal calls), one rule whichever client makes the call:
|
|
29
|
+
*
|
|
30
|
+
* 1. None for a host `no_proxy` / `NO_PROXY` names (envProxyFor's list).
|
|
31
|
+
* 2. The `proxy` plugin option when it is set, for http and https alike,
|
|
32
|
+
* except for a loopback host (`localhost`, 127.x, ::1): a proxy elsewhere
|
|
33
|
+
* can't reach this machine's loopback.
|
|
34
|
+
* 3. Else the environment's proxy for the URL's scheme (envProxyFor).
|
|
35
|
+
*
|
|
36
|
+
* Through 2.15 the option reached one call, the create a hub sends to a node
|
|
37
|
+
* or a cloud provider; that session's commands, screenshots and heartbeats,
|
|
38
|
+
* device control, the sockets and a node's calls to its hub took the
|
|
39
|
+
* environment's proxy instead, or none.
|
|
40
|
+
*/
|
|
41
|
+
function outboundProxyFor(target, opts = {}) {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
const url = toUrl(target);
|
|
44
|
+
const scheme = schemeOf(url);
|
|
45
|
+
if (!scheme)
|
|
46
|
+
return undefined;
|
|
47
|
+
const env = (_a = opts.env) !== null && _a !== void 0 ? _a : process.env;
|
|
48
|
+
if (namedByNoProxy(url, env))
|
|
49
|
+
return undefined;
|
|
50
|
+
const option = 'option' in opts ? opts.option : pluginProxyOption();
|
|
51
|
+
const configured = proxyOptionUrl(option, (_b = opts.warn) !== null && _b !== void 0 ? _b : warnOnce);
|
|
52
|
+
if (configured && !isLoopback(url.hostname))
|
|
53
|
+
return configured;
|
|
54
|
+
return schemeProxy(scheme, env);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The environment's proxy for a URL, by the rule axios (0.27's http adapter)
|
|
58
|
+
* applies to Xenon's axios calls:
|
|
59
|
+
* - `http_proxy` or `HTTP_PROXY` for an http URL, `https_proxy` or
|
|
60
|
+
* `HTTPS_PROXY` for an https one, the lower-case name first (ws and wss
|
|
61
|
+
* count as http and https);
|
|
62
|
+
* - none when `no_proxy` or `NO_PROXY` (the lower-case name first; a
|
|
63
|
+
* comma-separated list) has `*`, the URL's host name, or a suffix of it
|
|
64
|
+
* starting with a dot (`.lab.example`). An entry is a host name only: one
|
|
65
|
+
* with a port matches nothing, as in axios.
|
|
66
|
+
*
|
|
67
|
+
* Through 2.15 a command forwarded to a node took HTTP_PROXY or HTTPS_PROXY
|
|
68
|
+
* whatever its scheme and ignored NO_PROXY, the live-preview and logcat
|
|
69
|
+
* sockets ignored every proxy, and so did a node fetching its hub's keys.
|
|
70
|
+
*/
|
|
71
|
+
function envProxyFor(target, env = process.env) {
|
|
72
|
+
const url = toUrl(target);
|
|
73
|
+
const scheme = schemeOf(url);
|
|
74
|
+
if (!scheme || namedByNoProxy(url, env))
|
|
75
|
+
return undefined;
|
|
76
|
+
return schemeProxy(scheme, env);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* An agent sending an HTTP request for `target` through its proxy, or
|
|
80
|
+
* undefined to go straight there: the request in absolute form to the proxy
|
|
81
|
+
* for an http URL, a CONNECT tunnel for an https one.
|
|
82
|
+
*/
|
|
83
|
+
function proxyAgentFor(target, tls = {}) {
|
|
84
|
+
const proxy = outboundProxyFor(target);
|
|
85
|
+
if (!proxy)
|
|
86
|
+
return undefined;
|
|
87
|
+
const url = toUrl(target);
|
|
88
|
+
return url.protocol === 'https:' ? new TunnelAgent(proxy, tls) : new http_proxy_agent_1.HttpProxyAgent(proxy);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* An agent opening a WebSocket for `target` (ws or wss) through its proxy, or
|
|
92
|
+
* undefined to go straight there. Always a CONNECT tunnel: an upgrade sent to
|
|
93
|
+
* a proxy in absolute form is not reliably passed on.
|
|
94
|
+
*/
|
|
95
|
+
function socketProxyAgentFor(target, tls = {}) {
|
|
96
|
+
const proxy = outboundProxyFor(target);
|
|
97
|
+
return proxy ? new TunnelAgent(proxy, tls) : undefined;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* An axios request's proxy settings for `target`: through its proxy's agent,
|
|
101
|
+
* or none. Either way `proxy: false`, since the decision is made here, by
|
|
102
|
+
* outboundProxyFor; axios's own lookup reads the environment only. With no
|
|
103
|
+
* proxy, the caller's own agents stay.
|
|
104
|
+
*/
|
|
105
|
+
function axiosProxyConfig(target, tls = {}) {
|
|
106
|
+
const agent = proxyAgentFor(target, tls);
|
|
107
|
+
return agent ? { proxy: false, httpAgent: agent, httpsAgent: agent } : { proxy: false };
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* A CONNECT tunnel that checks the server behind it as the caller asked.
|
|
111
|
+
* HttpsProxyAgent's own options are for the connection to the proxy; the
|
|
112
|
+
* tunnelled TLS takes the request's, which axios doesn't fill in. So through
|
|
113
|
+
* 2.15 `tlsRejectUnauthorized` never reached a node or cloud provider that a
|
|
114
|
+
* proxy stood in front of.
|
|
115
|
+
*/
|
|
116
|
+
class TunnelAgent extends https_proxy_agent_1.HttpsProxyAgent {
|
|
117
|
+
constructor(proxy, targetTls) {
|
|
118
|
+
super(proxy);
|
|
119
|
+
this.targetTls = targetTls;
|
|
120
|
+
}
|
|
121
|
+
connect(req, opts) {
|
|
122
|
+
const _super = Object.create(null, {
|
|
123
|
+
connect: { get: () => super.connect }
|
|
124
|
+
});
|
|
125
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
126
|
+
const tls = this.targetTls.rejectUnauthorized === undefined
|
|
127
|
+
? {}
|
|
128
|
+
: { rejectUnauthorized: this.targetTls.rejectUnauthorized };
|
|
129
|
+
return _super.connect.call(this, req, Object.assign(Object.assign({}, opts), tls));
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The `proxy` option as a proxy URL: a string as it is (http:// added when
|
|
135
|
+
* it names no scheme), or `{ protocol, host, port, auth: { username,
|
|
136
|
+
* password } }` (protocol http by default, credentials escaped). One that
|
|
137
|
+
* names no host is no proxy, said once.
|
|
138
|
+
*/
|
|
139
|
+
function proxyOptionUrl(option, warn) {
|
|
140
|
+
var _a, _b;
|
|
141
|
+
if (option === undefined || option === null || option === '')
|
|
142
|
+
return undefined;
|
|
143
|
+
if (typeof option === 'string') {
|
|
144
|
+
const text = option.trim();
|
|
145
|
+
if (text === '')
|
|
146
|
+
return undefined;
|
|
147
|
+
return hasScheme(text) ? text : `http://${text}`;
|
|
148
|
+
}
|
|
149
|
+
const value = option;
|
|
150
|
+
if (typeof option !== 'object' || typeof value.host !== 'string' || value.host.trim() === '') {
|
|
151
|
+
warn(`The proxy option ${JSON.stringify(option)} names no host, so it is not used: ` +
|
|
152
|
+
"Xenon's calls to other servers take the environment's proxy, if any.");
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
const protocol = typeof value.protocol === 'string' && value.protocol !== ''
|
|
156
|
+
? value.protocol.replace(/:$/, '')
|
|
157
|
+
: 'http';
|
|
158
|
+
const port = value.port === undefined || value.port === null ? '' : `:${value.port}`;
|
|
159
|
+
const username = (_a = value.auth) === null || _a === void 0 ? void 0 : _a.username;
|
|
160
|
+
const password = (_b = value.auth) === null || _b === void 0 ? void 0 : _b.password;
|
|
161
|
+
const credentials = typeof username === 'string' && username !== ''
|
|
162
|
+
? `${encodeURIComponent(username)}${typeof password === 'string' ? `:${encodeURIComponent(password)}` : ''}@`
|
|
163
|
+
: '';
|
|
164
|
+
return `${protocol}://${credentials}${value.host.trim()}${port}`;
|
|
165
|
+
}
|
|
166
|
+
const warned = new Set();
|
|
167
|
+
function warnOnce(message) {
|
|
168
|
+
if (warned.has(message))
|
|
169
|
+
return;
|
|
170
|
+
warned.add(message);
|
|
171
|
+
logger_1.default.warn(message);
|
|
172
|
+
}
|
|
173
|
+
function pluginProxyOption() {
|
|
174
|
+
var _a;
|
|
175
|
+
try {
|
|
176
|
+
return (_a = typedi_1.Container.get(PluginContext_1.PluginContext).pluginArgs) === null || _a === void 0 ? void 0 : _a.proxy;
|
|
177
|
+
}
|
|
178
|
+
catch (_b) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function toUrl(target) {
|
|
183
|
+
return typeof target === 'string' ? new URL(target) : target;
|
|
184
|
+
}
|
|
185
|
+
function schemeOf(url) {
|
|
186
|
+
const scheme = url.protocol.replace(/:$/, '').replace(/^ws(s?)$/, 'http$1');
|
|
187
|
+
return scheme === 'http' || scheme === 'https' ? scheme : undefined;
|
|
188
|
+
}
|
|
189
|
+
function hostOf(url) {
|
|
190
|
+
return url.hostname.replace(/^\[(.*)\]$/, '$1');
|
|
191
|
+
}
|
|
192
|
+
function namedByNoProxy(url, env) {
|
|
193
|
+
const noProxy = env.no_proxy || env.NO_PROXY;
|
|
194
|
+
if (!noProxy)
|
|
195
|
+
return false;
|
|
196
|
+
const host = hostOf(url);
|
|
197
|
+
return noProxy
|
|
198
|
+
.split(',')
|
|
199
|
+
.map((entry) => entry.trim())
|
|
200
|
+
.some((entry) => entry !== '' &&
|
|
201
|
+
(entry === '*' || entry === host || (entry.startsWith('.') && host.endsWith(entry))));
|
|
202
|
+
}
|
|
203
|
+
function schemeProxy(scheme, env) {
|
|
204
|
+
const proxy = env[`${scheme}_proxy`] || env[`${scheme.toUpperCase()}_PROXY`];
|
|
205
|
+
if (!proxy)
|
|
206
|
+
return undefined;
|
|
207
|
+
return hasScheme(proxy) ? proxy : `http://${proxy}`;
|
|
208
|
+
}
|
|
209
|
+
function hasScheme(text) {
|
|
210
|
+
return /^[a-z][a-z0-9+.-]*:\/\//i.test(text);
|
|
211
|
+
}
|
|
212
|
+
function isLoopback(hostname) {
|
|
213
|
+
const host = hostname.replace(/^\[(.*)\]$/, '$1').toLowerCase();
|
|
214
|
+
return (host === 'localhost' ||
|
|
215
|
+
host.endsWith('.localhost') ||
|
|
216
|
+
/^127(\.\d{1,3}){3}$/.test(host) ||
|
|
217
|
+
host === '::1' ||
|
|
218
|
+
host === '0:0:0:0:0:0:0:1');
|
|
219
|
+
}
|
package/lib/src/index.js
CHANGED
|
@@ -68,6 +68,12 @@ const cleanup = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
68
68
|
// Bounded so a hung driver can't hold up systemd (default 90s timeout).
|
|
69
69
|
const { ShutdownCoordinator } = yield Promise.resolve().then(() => __importStar(require('./services/ShutdownCoordinator')));
|
|
70
70
|
yield typedi_1.Container.get(ShutdownCoordinator).drain(15000);
|
|
71
|
+
// Telemetry next, as early as it can be: on SIGTERM Appium exits before
|
|
72
|
+
// Phase 2 (see the 'exit' hook below), and placed last it never ran. What
|
|
73
|
+
// the OTel exporters still hold is sent, and the spans of sessions still
|
|
74
|
+
// running on a node or at a cloud provider end, saying so. Lines logged
|
|
75
|
+
// after this aren't exported.
|
|
76
|
+
yield shutDownTelemetry(3000);
|
|
71
77
|
const { default: IOSStreamService } = yield Promise.resolve().then(() => __importStar(require('./device-managers/ios/IOSStreamService')));
|
|
72
78
|
const { default: AndroidStreamService } = yield Promise.resolve().then(() => __importStar(require('./device-managers/android/AndroidStreamService')));
|
|
73
79
|
const { LogcatStreamService } = yield Promise.resolve().then(() => __importStar(require('./device-managers/android/LogcatStreamService')));
|
|
@@ -94,11 +100,26 @@ const cleanup = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
94
100
|
logger_1.default.error(`❌ [Xenon] Cleanup failed: ${err.message}`);
|
|
95
101
|
}
|
|
96
102
|
finally {
|
|
103
|
+
// When the drain threw, the telemetry wasn't shut down above. A second
|
|
104
|
+
// call does nothing.
|
|
105
|
+
yield shutDownTelemetry(1000);
|
|
97
106
|
// Principal Delay: Wait 2 seconds before hard-exiting to allow
|
|
98
107
|
// other async handlers (like hub unregistration) to finish.
|
|
99
108
|
setTimeout(() => process.exit(0), 2000);
|
|
100
109
|
}
|
|
101
110
|
});
|
|
111
|
+
function shutDownTelemetry(budgetMs) {
|
|
112
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
+
var _a;
|
|
114
|
+
try {
|
|
115
|
+
const { TracingService } = yield Promise.resolve().then(() => __importStar(require('./services/TracingService')));
|
|
116
|
+
yield typedi_1.Container.get(TracingService).shutdownWithin(budgetMs);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
logger_1.default.warn(`[Xenon] Telemetry shutdown failed: ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}`);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
102
123
|
process.on('SIGINT', cleanup);
|
|
103
124
|
process.on('SIGTERM', cleanup);
|
|
104
125
|
// Last-resort synchronous net for every long-lived sidecar.
|