@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
|
@@ -14,9 +14,26 @@
|
|
|
14
14
|
* - A name Xenon doesn't have fails with `unknown command`.
|
|
15
15
|
*/
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.XENON_SCRIPT_NAMES = void 0;
|
|
17
|
+
exports.XENON_SCRIPT_NAMES = exports.NETWORK_CAPTURE_SCRIPTS = void 0;
|
|
18
|
+
exports.interceptorScriptName = interceptorScriptName;
|
|
19
|
+
exports.isNetworkCaptureScript = isNetworkCaptureScript;
|
|
18
20
|
exports.xenonScriptName = xenonScriptName;
|
|
19
21
|
exports.unknownXenonScriptMessage = unknownXenonScriptMessage;
|
|
22
|
+
/**
|
|
23
|
+
* The scripts CommandInterceptor answers from the session's network capture.
|
|
24
|
+
* Their arguments and answers are the capture (requests, HAR, mocks), which
|
|
25
|
+
* REST shows to admins only, so the command log keeps neither (commandLogFields).
|
|
26
|
+
* A new script that answers from the capture goes in this list. A hub hides
|
|
27
|
+
* by its own copy, so it needs the release that adds the script.
|
|
28
|
+
*/
|
|
29
|
+
exports.NETWORK_CAPTURE_SCRIPTS = [
|
|
30
|
+
'addMock',
|
|
31
|
+
'removeMock',
|
|
32
|
+
'clearMocks',
|
|
33
|
+
'getMocks',
|
|
34
|
+
'getRequests',
|
|
35
|
+
'exportHar',
|
|
36
|
+
];
|
|
20
37
|
/** The names CommandInterceptor and the session-details commands answer. Keep in step with both. */
|
|
21
38
|
exports.XENON_SCRIPT_NAMES = [
|
|
22
39
|
'setAutowaitProperties',
|
|
@@ -29,18 +46,22 @@ exports.XENON_SCRIPT_NAMES = [
|
|
|
29
46
|
'analyzeScreen',
|
|
30
47
|
'omniScan',
|
|
31
48
|
'assertVisualState',
|
|
32
|
-
|
|
33
|
-
'removeMock',
|
|
34
|
-
'clearMocks',
|
|
35
|
-
'getMocks',
|
|
36
|
-
'getRequests',
|
|
37
|
-
'exportHar',
|
|
49
|
+
...exports.NETWORK_CAPTURE_SCRIPTS,
|
|
38
50
|
'setSessionName',
|
|
39
51
|
'setSessionStatus',
|
|
40
52
|
'debug',
|
|
41
53
|
'addTag',
|
|
42
54
|
'captureEvidence',
|
|
43
55
|
];
|
|
56
|
+
/** The name CommandInterceptor routes a script by: its `xe:` / `xenon:` prefix, if any, taken off. */
|
|
57
|
+
function interceptorScriptName(script) {
|
|
58
|
+
return script.replace(/^(xe|xenon)\s*:\s*/, '').trim();
|
|
59
|
+
}
|
|
60
|
+
/** Whether CommandInterceptor answers `script` from the session's network capture. */
|
|
61
|
+
function isNetworkCaptureScript(script) {
|
|
62
|
+
return (typeof script === 'string' &&
|
|
63
|
+
exports.NETWORK_CAPTURE_SCRIPTS.includes(interceptorScriptName(script)));
|
|
64
|
+
}
|
|
44
65
|
/** The name in a `xenon: <name>` or `xe: <name>` script, or null for any other script. */
|
|
45
66
|
function xenonScriptName(script) {
|
|
46
67
|
if (typeof script !== 'string')
|
package/lib/src/logger.js
CHANGED
|
@@ -185,7 +185,9 @@ class XenonLogger {
|
|
|
185
185
|
}
|
|
186
186
|
if (redactedArgs.length)
|
|
187
187
|
logEntry.args = redactedArgs;
|
|
188
|
-
|
|
188
|
+
// At its own level, so --log-level filters it and an error reaches
|
|
189
|
+
// stderr, as in text mode.
|
|
190
|
+
this.baseLogger[level](JSON.stringify(logEntry));
|
|
189
191
|
}
|
|
190
192
|
else {
|
|
191
193
|
const ctxPrefix = this.buildTextPrefix(ctx);
|
|
@@ -24,7 +24,13 @@ const PluginContext_1 = require("../PluginContext");
|
|
|
24
24
|
const hubSessionToken_1 = require("../gateway/hubSessionToken");
|
|
25
25
|
const localDeviceHosts_1 = require("../device-managers/localDeviceHosts");
|
|
26
26
|
const SESSION_COOKIE = 'xenon_dashboard_session';
|
|
27
|
-
|
|
27
|
+
/** An API key's expiresAt as epoch ms, or undefined for a key that never expires. */
|
|
28
|
+
function keyExpiresAt(expiresAt) {
|
|
29
|
+
if (!expiresAt)
|
|
30
|
+
return undefined;
|
|
31
|
+
const ms = new Date(expiresAt).getTime();
|
|
32
|
+
return Number.isNaN(ms) ? undefined : ms;
|
|
33
|
+
}
|
|
28
34
|
// Role → scopes derivation. The same table is used in profile token creation
|
|
29
35
|
// to enforce that members can never grant 'admin'.
|
|
30
36
|
// Cookie-session scopes: a logged-in user gets the full set of scopes
|
|
@@ -185,6 +191,7 @@ function authMiddleware(req, res, next) {
|
|
|
185
191
|
apiKeyId: row.id,
|
|
186
192
|
rateLimit: row.rateLimit,
|
|
187
193
|
teamIds,
|
|
194
|
+
credentialExpiresAt: keyExpiresAt(row.expiresAt),
|
|
188
195
|
};
|
|
189
196
|
req.apiKey = { id: row.id, scopes: row.scopes, rateLimit: row.rateLimit, teamId: (_b = row.teamId) !== null && _b !== void 0 ? _b : null };
|
|
190
197
|
return next();
|
|
@@ -224,6 +231,7 @@ function authMiddleware(req, res, next) {
|
|
|
224
231
|
teamId: (_e = payload.teamId) !== null && _e !== void 0 ? _e : null,
|
|
225
232
|
rateLimit: 300,
|
|
226
233
|
teamIds,
|
|
234
|
+
credentialExpiresAt: typeof payload.exp === 'number' ? payload.exp * 1000 : undefined,
|
|
227
235
|
};
|
|
228
236
|
return next();
|
|
229
237
|
}
|
|
@@ -242,11 +250,14 @@ function authMiddleware(req, res, next) {
|
|
|
242
250
|
if (!user || user.status !== 'ACTIVE')
|
|
243
251
|
return res.status(401).json({ error: 'invalid session' });
|
|
244
252
|
const isSecure = req.secure || req.headers['x-forwarded-proto'] === 'https';
|
|
253
|
+
// Renewed for as long as the session row now lasts
|
|
254
|
+
// (XENON_USER_SESSION_TTL_MS). A fixed 24 hours here capped any longer
|
|
255
|
+
// setting: the browser dropped the cookie after a day away.
|
|
245
256
|
res.cookie(SESSION_COOKIE, cookie, {
|
|
246
257
|
httpOnly: true,
|
|
247
258
|
secure: isSecure,
|
|
248
259
|
sameSite: 'strict',
|
|
249
|
-
maxAge:
|
|
260
|
+
maxAge: userSessionSvc.ttlMs(),
|
|
250
261
|
});
|
|
251
262
|
const teamIds = yield (0, callerTeamIds_1.computeTeamIds)({
|
|
252
263
|
role: user.role,
|
|
@@ -279,7 +290,7 @@ function authMiddleware(req, res, next) {
|
|
|
279
290
|
httpOnly: true,
|
|
280
291
|
secure: isSecure,
|
|
281
292
|
sameSite: 'strict',
|
|
282
|
-
maxAge:
|
|
293
|
+
maxAge: userSessionSvc.ttlMs(),
|
|
283
294
|
});
|
|
284
295
|
const teamIds = yield (0, callerTeamIds_1.computeTeamIds)({
|
|
285
296
|
role: user.role,
|
|
@@ -295,6 +306,7 @@ function authMiddleware(req, res, next) {
|
|
|
295
306
|
apiKeyId: row.id,
|
|
296
307
|
rateLimit: row.rateLimit,
|
|
297
308
|
teamIds,
|
|
309
|
+
credentialExpiresAt: keyExpiresAt(row.expiresAt),
|
|
298
310
|
};
|
|
299
311
|
req.apiKey = { id: row.id, scopes: row.scopes, rateLimit: row.rateLimit, teamId: (_g = row.teamId) !== null && _g !== void 0 ? _g : null };
|
|
300
312
|
return next();
|
|
@@ -103,9 +103,9 @@ class CommandCallerVerifier {
|
|
|
103
103
|
if (!out)
|
|
104
104
|
return null;
|
|
105
105
|
// A Bearer token carries the scopes of the credential that minted it
|
|
106
|
-
// (/auth/token), so it is judged like a key. Judging it by role alone
|
|
107
|
-
//
|
|
108
|
-
//
|
|
106
|
+
// (/auth/token), so it is judged like a key. Judging it by role alone
|
|
107
|
+
// would let an ADMIN's ordinary key mint its way to an override, as a
|
|
108
|
+
// xenon-session token's lease override did through 2.14.
|
|
109
109
|
return {
|
|
110
110
|
caller: {
|
|
111
111
|
userId: out.user.id,
|
|
@@ -42,9 +42,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
42
42
|
});
|
|
43
43
|
};
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.ACCEPTED_BEARER_AUDIENCES = void 0;
|
|
45
|
+
exports.SessionTokenSubjectError = exports.ACCEPTED_BEARER_AUDIENCES = void 0;
|
|
46
46
|
exports.verifyKeyPairCredential = verifyKeyPairCredential;
|
|
47
47
|
exports.verifyBearerCredential = verifyBearerCredential;
|
|
48
|
+
exports.isWrongSessionToken = isWrongSessionToken;
|
|
49
|
+
exports.verifySessionTokenCredential = verifySessionTokenCredential;
|
|
48
50
|
const jose = __importStar(require("jose"));
|
|
49
51
|
const typedi_1 = require("typedi");
|
|
50
52
|
const ApiKeyService_1 = require("../services/ApiKeyService");
|
|
@@ -96,6 +98,12 @@ function verifyKeyPairCredential(accessKey, token) {
|
|
|
96
98
|
* JWT) means the token is wrong. Any other error (typically "JWT key service
|
|
97
99
|
* not initialized") means it could not be checked, and is rethrown once no
|
|
98
100
|
* audience has verified.
|
|
101
|
+
*
|
|
102
|
+
* The payload's `scopes` are the token's as of now: `admin` is dropped once
|
|
103
|
+
* its user is a MEMBER. A token's scopes are fixed when it is minted, for up
|
|
104
|
+
* to a day, and REST (resolveActor, scopeGuard) and per-command auth's
|
|
105
|
+
* override read them, so through 2.14 an admin demoted since kept admin
|
|
106
|
+
* powers until the token expired.
|
|
99
107
|
*/
|
|
100
108
|
function verifyBearerCredential(token) {
|
|
101
109
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -119,6 +127,55 @@ function verifyBearerCredential(token) {
|
|
|
119
127
|
const user = yield typedi_1.Container.get(UserService_1.UserService).findById(String(payload.sub));
|
|
120
128
|
if (!user || user.status !== 'ACTIVE')
|
|
121
129
|
return null;
|
|
130
|
+
return { payload: Object.assign(Object.assign({}, payload), { scopes: scopesForLiveRole(payload.scopes, user.role) }), user };
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/** A token's `scopes` claim without `admin` when its user is now a MEMBER. */
|
|
134
|
+
function scopesForLiveRole(scopes, role) {
|
|
135
|
+
const list = String(scopes !== null && scopes !== void 0 ? scopes : '')
|
|
136
|
+
.split(',')
|
|
137
|
+
.map((s) => s.trim())
|
|
138
|
+
.filter(Boolean);
|
|
139
|
+
if (role === 'ADMIN' || role === 'SUPER_ADMIN')
|
|
140
|
+
return list.join(',');
|
|
141
|
+
return list.filter((s) => s !== 'admin').join(',');
|
|
142
|
+
}
|
|
143
|
+
/** The subject of a session token is no longer an ACTIVE user (deleted or Inactive). */
|
|
144
|
+
class SessionTokenSubjectError extends Error {
|
|
145
|
+
constructor() {
|
|
146
|
+
super('the session token names a user who is deleted or not active');
|
|
147
|
+
this.name = 'SessionTokenSubjectError';
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
exports.SessionTokenSubjectError = SessionTokenSubjectError;
|
|
151
|
+
/**
|
|
152
|
+
* Whether verifySessionTokenCredential's error means the token is wrong (a
|
|
153
|
+
* bad signature, audience or lifetime, not a JWT, or a departed user), as
|
|
154
|
+
* opposed to a check that could not run (the signing key or the database
|
|
155
|
+
* unavailable). A wrong token counts as none; a check that could not run
|
|
156
|
+
* refuses the create, as a key whose owner can't be looked up does.
|
|
157
|
+
*/
|
|
158
|
+
function isWrongSessionToken(err) {
|
|
159
|
+
return err instanceof jose.errors.JOSEError || err instanceof SessionTokenSubjectError;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* A `xenon-session` token (the `xe:options.sessionToken` capability), checked
|
|
163
|
+
* as REST checks a Bearer token: a valid signature, audience and lifetime,
|
|
164
|
+
* and a subject who is an ACTIVE user, looked up now. Through 2.14 session
|
|
165
|
+
* create checked the signature alone, so a deleted or Inactive user's token
|
|
166
|
+
* created sessions as them until it expired.
|
|
167
|
+
*
|
|
168
|
+
* Throws for a token that does not verify, as JwtKeyService.verify does, so
|
|
169
|
+
* the session-token gate and attribution treat a wrong signature and a
|
|
170
|
+
* departed user alike. Whether the token may create sessions at all (its
|
|
171
|
+
* `scopes`) is the caller's to judge.
|
|
172
|
+
*/
|
|
173
|
+
function verifySessionTokenCredential(token) {
|
|
174
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
175
|
+
const payload = yield typedi_1.Container.get(JwtKeyService_1.JwtKeyService).verify(token, { audience: 'xenon-session' });
|
|
176
|
+
const user = yield typedi_1.Container.get(UserService_1.UserService).findById(String(payload.sub));
|
|
177
|
+
if (!user || user.status !== 'ACTIVE')
|
|
178
|
+
throw new SessionTokenSubjectError();
|
|
122
179
|
return { payload, user: user };
|
|
123
180
|
});
|
|
124
181
|
}
|
package/lib/src/plugin.js
CHANGED
|
@@ -66,6 +66,7 @@ const IPluginArgs_1 = require("./interfaces/IPluginArgs");
|
|
|
66
66
|
const NodeDevices_1 = __importDefault(require("./device-managers/NodeDevices"));
|
|
67
67
|
const appiumUmbrella_1 = require("./sessions/appiumUmbrella");
|
|
68
68
|
const LiveSessionOwners_1 = require("./services/device-access/LiveSessionOwners");
|
|
69
|
+
const sessionMemory_1 = require("./sessions/sessionMemory");
|
|
69
70
|
const SessionMetricsService_1 = require("./services/metrics/SessionMetricsService");
|
|
70
71
|
const PhoneNetworkRestore_1 = require("./services/network/PhoneNetworkRestore");
|
|
71
72
|
const config_1 = require("./config");
|
|
@@ -73,6 +74,7 @@ const SessionManager_1 = require("./sessions/SessionManager");
|
|
|
73
74
|
const event_manager_1 = require("./dashboard/event-manager");
|
|
74
75
|
const asset_manager_1 = require("./dashboard/asset-manager");
|
|
75
76
|
const session_service_1 = require("./dashboard/services/session-service");
|
|
77
|
+
const shutdownReason_1 = require("./services/session/shutdownReason");
|
|
76
78
|
const DEVICE_MANAGER_LOCK_NAME = 'DeviceManager';
|
|
77
79
|
class XenonPlugin extends base_plugin_1.default {
|
|
78
80
|
constructor(pluginName, cliArgs) {
|
|
@@ -104,11 +106,20 @@ class XenonPlugin extends base_plugin_1.default {
|
|
|
104
106
|
return yield typedi_1.Container.get(CommandInterceptor_1.CommandInterceptor).handle(next, driver, commandName, args, this.pluginArgs, XenonPlugin.IS_HUB);
|
|
105
107
|
});
|
|
106
108
|
}
|
|
107
|
-
onUnexpectedShutdown(driver,
|
|
109
|
+
onUnexpectedShutdown(driver, cause) {
|
|
108
110
|
return __awaiter(this, void 0, void 0, function* () {
|
|
109
111
|
var _a;
|
|
110
112
|
const sessionId = driver.sessionId;
|
|
111
113
|
typedi_1.Container.get(LiveSessionOwners_1.LiveSessionOwners).forget(sessionId);
|
|
114
|
+
(0, sessionMemory_1.forgetSessionMemory)(sessionId);
|
|
115
|
+
// With the dashboard on or off: this was the only place a session span
|
|
116
|
+
// ended, and only with the dashboard on.
|
|
117
|
+
if (sessionId) {
|
|
118
|
+
typedi_1.Container.get(TracingService_1.TracingService).endSessionSpan(sessionId, {
|
|
119
|
+
failed: true,
|
|
120
|
+
reason: (0, shutdownReason_1.unexpectedShutdownReason)(cause),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
112
123
|
if (sessionId)
|
|
113
124
|
yield typedi_1.Container.get(SessionMetricsService_1.SessionMetricsService).stop(sessionId);
|
|
114
125
|
// Appium's new-command timeout ends a session here, not in deleteSession:
|
|
@@ -136,7 +147,9 @@ class XenonPlugin extends base_plugin_1.default {
|
|
|
136
147
|
logger_1.default.info(`Unblocking device mapped with filter ${JSON.stringify(deviceFilter)} onUnexpectedShutdown from server`);
|
|
137
148
|
if (XenonPlugin.IS_HUB && this.pluginArgs.enableDashboard && sessionId) {
|
|
138
149
|
const sessionLog = this.xenonLog.withSession(sessionId, (_a = driver.caps) === null || _a === void 0 ? void 0 : _a.udid);
|
|
139
|
-
|
|
150
|
+
// Appium's cause, so an idle session is filed as a timeout.
|
|
151
|
+
const reason = (0, shutdownReason_1.unexpectedShutdownReason)(cause);
|
|
152
|
+
sessionLog.info(`Unexpected shutdown for session (${reason}), updating dashboard...`);
|
|
140
153
|
const session = SessionManager_1.SESSION_MANAGER.getSession(sessionId);
|
|
141
154
|
if (session && session.isVideoRecordingInProgress()) {
|
|
142
155
|
try {
|
|
@@ -154,10 +167,7 @@ class XenonPlugin extends base_plugin_1.default {
|
|
|
154
167
|
logger_1.default.debug(`[${sessionId}] rescue-video: Failed: ${err.message}`);
|
|
155
168
|
}
|
|
156
169
|
}
|
|
157
|
-
yield event_manager_1.DASHBORD_EVENT_MANAGER.onSessionStopped(sessionId, SessionStatus_1.SessionStatus.FAILED,
|
|
158
|
-
typedi_1.Container.get(TracingService_1.TracingService).endSpan(sessionId, 'ERROR', {
|
|
159
|
-
'xenon.session.stop_reason': 'Unexpected shutdown',
|
|
160
|
-
});
|
|
170
|
+
yield event_manager_1.DASHBORD_EVENT_MANAGER.onSessionStopped(sessionId, SessionStatus_1.SessionStatus.FAILED, reason);
|
|
161
171
|
}
|
|
162
172
|
});
|
|
163
173
|
}
|
|
@@ -93,9 +93,9 @@ function checkDatabase(opts) {
|
|
|
93
93
|
}
|
|
94
94
|
if (configured && configured !== client) {
|
|
95
95
|
return {
|
|
96
|
-
warning: `[Database] databaseProvider is "${configured}",
|
|
97
|
-
`
|
|
98
|
-
`
|
|
96
|
+
warning: `[Database] databaseProvider is "${configured}", which has no effect: this install ` +
|
|
97
|
+
`stores its data in ${clientLabel}, in ${where}, and the database itself decides how ` +
|
|
98
|
+
`its schema is brought up to date. Remove the setting, or set it to "${client}".`,
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
101
|
return {};
|
|
@@ -14,42 +14,44 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const node_child_process_1 = require("node:child_process");
|
|
16
16
|
const config_1 = require("../config");
|
|
17
|
-
const prepare_prisma_1 = require("./prepare-prisma");
|
|
18
17
|
const logger_1 = __importDefault(require("../logger"));
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
18
|
+
const database_check_1 = require("./database-check");
|
|
19
|
+
const run_migrations_1 = require("./run-migrations");
|
|
20
|
+
/**
|
|
21
|
+
* `npm run db:migrate`: bring the database up to date, then regenerate the
|
|
22
|
+
* client.
|
|
23
|
+
*
|
|
24
|
+
* It checks the database URL and uses the rule the server uses at startup
|
|
25
|
+
* (database-check.ts, then run-migrations.ts): the database decides between
|
|
26
|
+
* `migrate deploy` and `db push`, so a database whose migration history
|
|
27
|
+
* matches its tables stays on `migrate deploy`. It runs whatever
|
|
28
|
+
* XENON_AUTO_MIGRATE says, since it is how you update the schema when that is
|
|
29
|
+
* off. Through 2.15.0 it always ran `db push`, and first rewrote
|
|
30
|
+
* prisma/schema.prisma's provider to `databaseProvider`. With `postgresql`,
|
|
31
|
+
* that left a PostgreSQL schema in the checkout that the SQLite file couldn't
|
|
32
|
+
* use.
|
|
33
|
+
*
|
|
34
|
+
* It first warns of changes to prisma/schema.prisma that no migration makes.
|
|
35
|
+
* `npm run db:generate` gives the developer's database a migration history, and
|
|
36
|
+
* from then on it is updated with `migrate deploy`, which never applies them,
|
|
37
|
+
* while the log said the schema was in sync.
|
|
38
|
+
*/
|
|
34
39
|
function main() {
|
|
35
40
|
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
logger_1.default.info('[DBInit] Syncing SQLite schema via db push...');
|
|
42
|
-
executeCmd('npx prisma db push --accept-data-loss --skip-generate');
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
// For PostgreSQL, we might not have migrations checked in yet.
|
|
46
|
-
// In "Cellular Architecture", we use db push to ensure the schema is synced
|
|
47
|
-
// without requiring migration history sync across cells.
|
|
48
|
-
logger_1.default.info('[DBInit] Syncing PostgreSQL schema via db push...');
|
|
49
|
-
executeCmd('npx prisma db push --accept-data-loss');
|
|
50
|
-
}
|
|
41
|
+
// A PostgreSQL URL would otherwise reach the history read and fail there,
|
|
42
|
+
// under a message about the file.
|
|
43
|
+
(0, database_check_1.assertSupportedDatabase)();
|
|
44
|
+
(0, run_migrations_1.warnOfUnmigratedSchemaChanges)();
|
|
45
|
+
yield (0, run_migrations_1.syncDatabaseSchema)();
|
|
51
46
|
logger_1.default.info('[DBInit] Generating Prisma Client...');
|
|
52
|
-
|
|
47
|
+
(0, node_child_process_1.execSync)('npx prisma generate', {
|
|
48
|
+
env: Object.assign(Object.assign({}, process.env), { DATABASE_URL: config_1.config.databaseUrl }),
|
|
49
|
+
stdio: 'inherit',
|
|
50
|
+
});
|
|
53
51
|
});
|
|
54
52
|
}
|
|
55
|
-
(() =>
|
|
53
|
+
main().catch((err) => {
|
|
54
|
+
var _a;
|
|
55
|
+
logger_1.default.error(`[DBInit] ${(_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err}`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
});
|