@camera.ui/server 0.0.69 → 0.0.71-dev.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/CLAUDE.md +91 -0
- package/README.md +0 -24
- package/cupdate.config.txt +0 -1
- package/dist/interface/assets/404-CIsBB4A0.js +1 -0
- package/dist/interface/assets/About-CkxZb9D-.js +1 -0
- package/dist/interface/assets/Adminpanel-BrZ55JBx.js +1 -0
- package/dist/interface/assets/Automation-BKhuIS2v.js +2 -0
- package/dist/interface/assets/Automation-Csu8t0D7.css +1 -0
- package/dist/interface/assets/Automations-CzdnqGGU.js +1 -0
- package/dist/interface/assets/Camera-BhCDJE7I.css +1 -0
- package/dist/interface/assets/Camera-CU3aKdBR.js +2 -0
- package/dist/interface/assets/CameraConsole-D7KxwRxQ.js +7 -0
- package/dist/interface/assets/Cameras-807mspcl.css +1 -0
- package/dist/interface/assets/Cameras-DJcAfGpU.js +656 -0
- package/dist/interface/assets/Camview-ArBQ3nES.js +1 -0
- package/dist/interface/assets/Camview-Dd7DwMHG.css +1 -0
- package/dist/interface/assets/Config-D2ftkjl2.js +2 -0
- package/dist/interface/assets/Config-JgftUZFe.css +1 -0
- package/dist/interface/assets/ConfigActionCameraControl-94iyzBzJ.js +1 -0
- package/dist/interface/assets/ConfigActionDelay-DKhE0Xr8.js +1 -0
- package/dist/interface/assets/ConfigActionHttp-BbfN1UGF.js +1 -0
- package/dist/interface/assets/ConfigActionImageInput-P39gRfld.js +1 -0
- package/dist/interface/assets/ConfigActionNotification-CuDDnksK.js +1 -0
- package/dist/interface/assets/ConfigActionOutput-BIHvC1Z5.js +1 -0
- package/dist/interface/assets/ConfigActionPlugin-CDA53LwA.js +1 -0
- package/dist/interface/assets/ConfigActionSensor-BBkfWT_r.js +1 -0
- package/dist/interface/assets/ConfigActionSnapshot-C5enxVcl.js +1 -0
- package/dist/interface/assets/ConfigActionVariable-CVaOMoOi.js +1 -0
- package/dist/interface/assets/ConfigConditionIfElse-DiIOUqA5.js +1 -0
- package/dist/interface/assets/ConfigConditionSensorState-DBktbA8F.js +1 -0
- package/dist/interface/assets/ConfigConditionSwitch-DWqcQ3Ip.js +1 -0
- package/dist/interface/assets/ConfigConditionTime-BEaHclqa.js +1 -0
- package/dist/interface/assets/ConfigTriggerDetection-CRnZR91p.js +1 -0
- package/dist/interface/assets/ConfigTriggerGeofence-DODdJBZW.js +1 -0
- package/dist/interface/assets/ConfigTriggerManual-V8-5hrdl.js +1 -0
- package/dist/interface/assets/ConfigTriggerSchedule-CqID85d1.js +1 -0
- package/dist/interface/assets/ConfigTriggerSensor-DR6ifBrK.js +1 -0
- package/dist/interface/assets/ConfigTriggerSystem-K1ohOW18.js +1 -0
- package/dist/interface/assets/ConfigTriggerWebhook-Cmwu5IU4.js +1 -0
- package/dist/interface/assets/Console-IC7AOnvc.js +6 -0
- package/dist/interface/assets/CuiActionButton-Ba5wT-4n.js +1 -0
- package/dist/interface/assets/CuiAvatar-BtMXnhxd.css +1 -0
- package/dist/interface/assets/CuiAvatar-Bu4NixiB.js +1 -0
- package/dist/interface/assets/CuiBBoxPlayground-Cmbd4_qG.js +1 -0
- package/dist/interface/assets/CuiBBoxPlayground-EFkdOBvq.css +1 -0
- package/dist/interface/assets/CuiBottomSheet-BN5exkJm.js +1 -0
- package/dist/interface/assets/CuiBottomSheet-CHspaYgP.js +1 -0
- package/dist/interface/assets/CuiBottomSheet-DxQ6D_RM.css +1 -0
- package/dist/interface/assets/CuiCameraCard-C7eDwhgw.js +1 -0
- package/dist/interface/assets/CuiCameraCard-dNsAwlKS.css +1 -0
- package/dist/interface/assets/CuiCameraPipCard-C8Pg7xT9.js +1 -0
- package/dist/interface/assets/CuiCameraPipCard-D3o29_wc.css +1 -0
- package/dist/interface/assets/CuiCameraRecordings-CQHbo-_J.js +1 -0
- package/dist/interface/assets/CuiCameraRecordings-DM_o0Lya.css +1 -0
- package/dist/interface/assets/CuiCameraShares-DNuCgk4b.js +1 -0
- package/dist/interface/assets/CuiCameraSnapshot-BpUMwSoR.js +1 -0
- package/dist/interface/assets/CuiCameraTable-DQffvTtY.js +2 -0
- package/dist/interface/assets/CuiFloatingButton-RaxwbGht.js +1 -0
- package/dist/interface/assets/CuiImage-60jwFIqc.js +1 -0
- package/dist/interface/assets/CuiImage-Bxf7z2N4.css +1 -0
- package/dist/interface/assets/CuiMarkdownContent-M5v8bBmS.js +1 -0
- package/dist/interface/assets/CuiMenu-B4CHT2F_.js +1 -0
- package/dist/interface/assets/CuiMenu-BWUfWLQP.css +1 -0
- package/dist/interface/assets/CuiPluginCard-5ItfIe1Z.js +2 -0
- package/dist/interface/assets/CuiPluginCard-CTTsEM9M.css +1 -0
- package/dist/interface/assets/CuiPluginOAuthButton-BJRU2JBX.js +2 -0
- package/dist/interface/assets/CuiQRCode-CNeepRQw.js +1 -0
- package/dist/interface/assets/CuiQRCode-DfUba6JB.css +1 -0
- package/dist/interface/assets/CuiRecordingsGrid-CKHFeJlJ.js +1 -0
- package/dist/interface/assets/CuiRecordingsGrid-CZIZiEuT.css +1 -0
- package/dist/interface/assets/CuiSchema--yMBD996.css +1 -0
- package/dist/interface/assets/CuiSchema-CTRLO0uq.js +1 -0
- package/dist/interface/assets/CuiTopNavbarItem-CgaR_X1z.js +1 -0
- package/dist/interface/assets/CuiTopNavbarItem-w54CrODK.css +1 -0
- package/dist/interface/assets/CuiTopbarSlot-BDZoZ_yn.js +1 -0
- package/dist/interface/assets/Faces-JoBk1Mcv.js +1 -0
- package/dist/interface/assets/FirstSteps-CSMvd_p0.js +1 -0
- package/dist/interface/assets/Instances-DwNihvsL.js +1 -0
- package/dist/interface/assets/Menu-CUnOgtD5.js +1 -0
- package/dist/interface/assets/OAuthDeviceFlow-aUHpE7wP.js +1 -0
- package/dist/interface/assets/Plugin-DoxdkvWR.css +1 -0
- package/dist/interface/assets/Plugin-LjpUwn17.js +1 -0
- package/dist/interface/assets/PluginConsole-CvDWPKOs.js +7 -0
- package/dist/interface/assets/PluginSchema-DL7Bfd_U.js +1 -0
- package/dist/interface/assets/Plugins-B207FOsG.js +2 -0
- package/dist/interface/assets/Plugins-BPt1RSKT.css +1 -0
- package/dist/interface/assets/Recordings-Bt_GlPOK.css +1 -0
- package/dist/interface/assets/Recordings-adHTSogQ.js +1 -0
- package/dist/interface/assets/Settings-bwLTNAxX.css +1 -0
- package/dist/interface/assets/Settings-iBjUbXTH.js +1 -0
- package/dist/interface/assets/SettingsAccount-Ce0UnkLb.js +1 -0
- package/dist/interface/assets/SettingsAccount-DXKQY4Iz.css +1 -0
- package/dist/interface/assets/SettingsAccount-f2wkt4kx.js +1 -0
- package/dist/interface/assets/SettingsAppearance-2TfnSgkI.js +1 -0
- package/dist/interface/assets/SettingsAppearance-Dca237An.js +1 -0
- package/dist/interface/assets/SettingsBackup-Bh5x-GU_.js +1 -0
- package/dist/interface/assets/SettingsNotifications-BVmhorXq.js +2 -0
- package/dist/interface/assets/SettingsRecordings-dPUm5hma.js +1 -0
- package/dist/interface/assets/SettingsRemote-BcVzn2m3.js +1 -0
- package/dist/interface/assets/SettingsRemote-CjVK9pGg.css +1 -0
- package/dist/interface/assets/SettingsSystem-Dz76BUJ-.js +2 -0
- package/dist/interface/assets/SettingsUsers-Dzj--Rmf.js +1 -0
- package/dist/interface/assets/Terminal-BAMMh8Px.js +4 -0
- package/dist/interface/assets/Terminal-CrOfQJ-O.css +1 -0
- package/dist/interface/assets/VariableInput-D_-qKfZK.js +1 -0
- package/dist/interface/assets/VariableSuggestions-Br4yDsLZ.js +1 -0
- package/dist/interface/assets/VersionsHandler-CfNT3Yke.js +7 -0
- package/dist/interface/assets/Workers-D3jFWBjm.js +1 -0
- package/dist/interface/assets/_plugin-vue_export-helper-BDNMzG2s.js +1 -0
- package/dist/interface/assets/ace-BRyQJK-L.js +1 -0
- package/dist/interface/assets/ace.config-fXRdG20S.js +1 -0
- package/dist/interface/assets/alert-outline-D3FCIX7_.js +1 -0
- package/dist/interface/assets/api-BaywoTCE.js +2 -0
- package/dist/interface/assets/api-Cna9Poda.css +2 -0
- package/dist/interface/assets/api-DvuXV3Xb.js +1 -0
- package/dist/interface/assets/auth-Cu-pUvKk.js +1 -0
- package/dist/interface/assets/automation-CbEPnAW4.js +1 -0
- package/dist/interface/assets/automations-Bj3wF0wR.js +1 -0
- package/dist/interface/assets/automations-C6ssihoC.js +1 -0
- package/dist/interface/assets/back-filled-CvLD0CND.js +1 -0
- package/dist/interface/assets/backup-DK5aZBLo.js +1 -0
- package/dist/interface/assets/bell-outline-JZZKpcfS.js +1 -0
- package/dist/interface/assets/camera-preview-C7GT5VHo.png +0 -0
- package/dist/interface/assets/cameras-DQ28quQb.js +1 -0
- package/dist/interface/assets/cameras.schema-CDeB5JeE.js +1 -0
- package/dist/interface/assets/cctv-SQFfbBnL.js +1 -0
- package/dist/interface/assets/check-BQQidcYi.js +1 -0
- package/dist/interface/assets/chevron-down-Dd1qHXVA.js +1 -0
- package/dist/interface/assets/chevron-right-DOmJR2OL.js +1 -0
- package/dist/interface/assets/circular-connection-nKCVm4QI.js +1 -0
- package/dist/interface/assets/close-Dhjo4o57.js +1 -0
- package/dist/interface/assets/close-WdhW_91X.js +1 -0
- package/dist/interface/assets/close-circle-i5PrRG0X.js +1 -0
- package/dist/interface/assets/close-rounded-6nzLVPw0.js +1 -0
- package/dist/interface/assets/cloud-check-DeN6leiB.js +1 -0
- package/dist/interface/assets/cloud-outline-BHjUiP9q.js +1 -0
- package/dist/interface/assets/cloud-outline-BQddJElX.js +1 -0
- package/dist/interface/assets/cloudHandoff-DxhttWWd.js +1 -0
- package/dist/interface/assets/cog-Batjj1se.js +1 -0
- package/dist/interface/assets/copy-16-filled-DuAEBVEX.js +1 -0
- package/dist/interface/assets/copy-BeuZDsJN.js +1 -0
- package/dist/interface/assets/delete-DvMWXBFV.js +1 -0
- package/dist/interface/assets/dist-CcCNy5h7.js +1 -0
- package/dist/interface/assets/download-Cna5QEEj.js +1 -0
- package/dist/interface/assets/esm-B4Pd2w1t.js +1 -0
- package/dist/interface/assets/esm-B4l8-ACY.js +1 -0
- package/dist/interface/assets/esm-BE98HKPg.js +1 -0
- package/dist/interface/assets/esm-BNSLSv2m.js +1 -0
- package/dist/interface/assets/esm-BnT9fzsT.js +1 -0
- package/dist/interface/assets/esm-C-uLCRX1.js +1 -0
- package/dist/interface/assets/esm-C6JCcz6o.js +1 -0
- package/dist/interface/assets/esm-D5_rxfjE.js +1 -0
- package/dist/interface/assets/esm-D6ymjVa1.js +1 -0
- package/dist/interface/assets/esm-D8teZoG1.js +1 -0
- package/dist/interface/assets/esm-DnSGrmvg.js +1 -0
- package/dist/interface/assets/esm-DqkQVzkL.js +1 -0
- package/dist/interface/assets/esm-tnu6qUMk.js +1 -0
- package/dist/interface/assets/eventIcons-2hVCNchU.css +1 -0
- package/dist/interface/assets/eventIcons-DVykqtE5.js +1 -0
- package/dist/interface/assets/face-recognition-5Yp1IcUb.js +1 -0
- package/dist/interface/assets/github-37yEERpu.js +1 -0
- package/dist/interface/assets/grid-fill-BGU3gqir.js +1 -0
- package/dist/interface/assets/hasPermission-DIF0bX8u.js +1 -0
- package/dist/interface/assets/home-sSF_NnOu.js +1 -0
- package/dist/interface/assets/information-outline-fu18_QSH.js +1 -0
- package/dist/interface/assets/instances-DGPhZWRw.js +1 -0
- package/dist/interface/assets/lightbulb-outline-DWc53kV7.js +1 -0
- package/dist/interface/assets/locale-Bm1nXzqV.js +1 -0
- package/dist/interface/assets/main-BqVSZVz1.css +1 -0
- package/dist/interface/assets/main-D1gFWXGG.js +3 -0
- package/dist/interface/assets/microphone-ChDR4mkG.js +1 -0
- package/dist/interface/assets/native-Cq3ra8E-.js +1 -0
- package/dist/interface/assets/native-DfLBhmBo.js +1 -0
- package/dist/interface/assets/nodeDefinitions-BLSMZueH.js +1 -0
- package/dist/interface/assets/notifications-DNRzOl89.js +1 -0
- package/dist/interface/assets/play-solid-B_749j1A.js +1 -0
- package/dist/interface/assets/plugin-C1NakF2p.js +1 -0
- package/dist/interface/assets/plugins-DzRwEcA4.js +1 -0
- package/dist/interface/assets/plus-B5eEboLZ.js +1 -0
- package/dist/interface/assets/plus-Dis0MPt8.js +1 -0
- package/dist/interface/assets/power-CxGfHa98.js +1 -0
- package/dist/interface/assets/ring-resize-fOkdAS5R.js +1 -0
- package/dist/interface/assets/rolldown-runtime-CMxvf4Kt.js +1 -0
- package/dist/interface/assets/round-alt-arrow-left-bold-ekP_ATNV.js +1 -0
- package/dist/interface/assets/round-restart-alt-BWTTuG_j.js +1 -0
- package/dist/interface/assets/round-restart-alt-CJgRaJjF.css +1 -0
- package/dist/interface/assets/router-CuAn6JZ_.css +1 -0
- package/dist/interface/assets/router-DGyFln7e.js +2 -0
- package/dist/interface/assets/routerState-DMVeYr60.js +1 -0
- package/dist/interface/assets/search-YdrT6au7.js +1 -0
- package/dist/interface/assets/server-BWxbeZzY.js +1 -0
- package/dist/interface/assets/settings-D2-mWioF.js +1 -0
- package/dist/interface/assets/shares-BLuBJftj.js +1 -0
- package/dist/interface/assets/shield-check-DFR-xg-g.js +1 -0
- package/dist/interface/assets/terminal-BYi6cqd4.js +1 -0
- package/dist/interface/assets/theme-D08Upl8q.js +1 -0
- package/dist/interface/assets/trash-2-Du7oioNA.js +1 -0
- package/dist/interface/assets/trash-can-YTXLzAmt.js +1 -0
- package/dist/interface/assets/trash-fill-ZI3YYgNp.js +1 -0
- package/dist/interface/assets/types-B_isDU64.js +1 -0
- package/dist/interface/assets/types-BxFyoO54.js +1 -0
- package/dist/interface/assets/types-kxdn9XBW.js +1 -0
- package/dist/interface/assets/ui-aYGNqaHi.js +1 -0
- package/dist/interface/assets/upload-Chr4Uunq.js +1 -0
- package/dist/interface/assets/useBiometricCredentials-B-zA6b-X.js +1 -0
- package/dist/interface/assets/useCameraOptions-0w0LNh72.js +1 -0
- package/dist/interface/assets/useCuiCameraDrawer-Dn97MLFe.js +1 -0
- package/dist/interface/assets/useCuiDialog-BbkaNkQN.js +2 -0
- package/dist/interface/assets/useElectron-mh8HQUAI.js +1 -0
- package/dist/interface/assets/useFileDownload-g3sM8lp6.js +1 -0
- package/dist/interface/assets/useLogsSocket-CZld674d.js +4 -0
- package/dist/interface/assets/useLogsSocket-pqdh7jNG.css +1 -0
- package/dist/interface/assets/useSharedComposables-riqEUgwX.js +1 -0
- package/dist/interface/assets/useStreamStatus-2lguNuWT.js +1 -0
- package/dist/interface/assets/users.schema-CUZOYClB.js +1 -0
- package/dist/interface/assets/vendor-DmhYd_sB.js +22 -0
- package/dist/interface/assets/vendor-ace-B9YSA4ub.js +1085 -0
- package/dist/interface/assets/vendor-cameraui-DggYb17u.js +1976 -0
- package/dist/interface/assets/vendor-capacitor-IA6kwsx8.js +2 -0
- package/dist/interface/assets/vendor-chart-Dnlz1Jgy.js +3 -0
- package/dist/interface/assets/vendor-core-B6F-imJj.js +1 -0
- package/dist/interface/assets/vendor-dnd-Dp0ottZI.js +2 -0
- package/dist/interface/assets/vendor-draggabilly-C2ae3o70.js +1 -0
- package/dist/interface/assets/vendor-gridstack-Dxjc1EeA.js +3 -0
- package/dist/interface/assets/vendor-gridstack-Rg2RhwAc.css +1 -0
- package/dist/interface/assets/vendor-leaflet-B5L2Aw8Y.js +1 -0
- package/dist/interface/assets/vendor-leaflet-vh-t_kPv.css +1 -0
- package/dist/interface/assets/vendor-markdown-D3nVi7gw.js +15 -0
- package/dist/interface/assets/vendor-markdown-DtOhvyRx.css +1 -0
- package/dist/interface/assets/vendor-primevue--pcuf6kA.js +4289 -0
- package/dist/interface/assets/vendor-vueflow-CBuKPASC.js +26 -0
- package/dist/interface/assets/vendor-xterm-BrP-ENHg.css +1 -0
- package/dist/interface/assets/vendor-xterm-D8Z_h2U0.js +145 -0
- package/dist/interface/assets/vendor-zod-CmGeQCqy.js +127 -0
- package/dist/interface/assets/view-grid-96p9T-KQ.js +1 -0
- package/dist/interface/assets/view-grid-SdzaC3O_.css +1 -0
- package/dist/interface/assets/web-3Sh2qjiP.js +1 -0
- package/dist/interface/assets/web-B0BK4Q2M.js +1 -0
- package/dist/interface/assets/web-BjKL51lK-DzG2kK8Q.js +1 -0
- package/dist/interface/assets/web-COttRPza.js +1 -0
- package/dist/interface/assets/web-Ck1J3gUt.js +1 -0
- package/dist/interface/assets/web-DPxPmEOR.js +1 -0
- package/dist/interface/assets/web-DRprnZwc.js +1 -0
- package/dist/interface/assets/web-DusfFKJE.js +1 -0
- package/dist/interface/assets/web-U3ajDFzM.js +1 -0
- package/dist/interface/assets/web-jcLz0P7f.js +1 -0
- package/dist/interface/assets/web-tQAiC0W2.js +1 -0
- package/dist/interface/assets/web-x9pvmNMf.js +1 -0
- package/dist/interface/assets/workbox-window.prod.es5-DkzC-kEO.js +1 -0
- package/dist/interface/assets/worker-base-ybazWkNy.js +1337 -0
- package/dist/interface/assets/worker-yaml-crtWQpDN.js +5824 -0
- package/dist/interface/assets/zoom-in-zoFmMkYM.js +1 -0
- package/dist/interface/index.html +96 -45
- package/dist/interface/manifest.webmanifest +1 -1
- package/dist/interface/og-share.png +0 -0
- package/dist/interface/sw.js +1 -1
- package/dist/interface/workbox-5f44db27.js +1 -0
- package/dist/server/package.json +73 -79
- package/dist/server/requirements.txt +9 -14
- package/dist/server/src/_camera_ui_tools/camera_ui_common/__init__.py +19 -11
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/__init__.py +23 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/object_path.py +35 -22
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/promise.py +41 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/reactive.py +17 -14
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/signal_handler.py +12 -4
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/subscribed.py +15 -2
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/task.py +9 -3
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/thread.py +10 -2
- package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/utils.py +21 -13
- package/dist/server/src/_camera_ui_tools/camera_ui_common/logger_service/__init__.py +8 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_common/logger_service/logger.py +237 -99
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/__init__.py +77 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/channel.py +321 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/chunking.py +290 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/client.py +1694 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/codec.py +73 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/decorators.py +307 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/errors.py +76 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/executor.py +29 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/handler.py +523 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/service.py +524 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/svcm.py +15 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/types.py +427 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc/utils.py +332 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/__init__.py +515 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/__init__.py +173 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/config.py +256 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/detection.py +135 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/device.py +432 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/enums.py +111 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/events.py +146 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/frames.py +21 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/streaming.py +188 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/__init__.py +92 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/camera_config_internal.py +46 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/camera_enums.py +9 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/camera_wire.py +15 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/event_emitter.py +102 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/manager_rpc.py +27 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/sensor_rpc.py +89 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/sensor_triggers.py +4 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/shared_utils.py +73 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/streaming_internal.py +16 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/manager/__init__.py +348 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/observable/__init__.py +557 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/__init__.py +104 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/api.py +137 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/contract.py +164 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/helper.py +242 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/interfaces.py +427 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/notifier.py +142 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/oauth.py +150 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/__init__.py +203 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/audio.py +241 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/base.py +551 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/battery.py +167 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/classifier.py +196 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/clip.py +67 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/contact.py +88 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/detection.py +60 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/doorbell.py +122 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/face.py +184 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/garage.py +174 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/humidity.py +79 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/leak.py +88 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/license_plate.py +186 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/light.py +157 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/lock.py +149 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/motion.py +203 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/object.py +210 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/occupancy.py +88 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/ptz.py +256 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/security_system.py +157 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/siren.py +150 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/smoke.py +88 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/spec.py +56 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/switch.py +107 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/temperature.py +80 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/storage/__init__.py +695 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_sdk/types.py +54 -0
- package/dist/server/src/api/controllers/api.controller.d.ts +2 -2
- package/dist/server/src/api/controllers/api.controller.js +3 -3
- package/dist/server/src/api/controllers/api.controller.js.map +1 -1
- package/dist/server/src/api/controllers/auth.controller.d.ts +20 -5
- package/dist/server/src/api/controllers/auth.controller.js +418 -134
- package/dist/server/src/api/controllers/auth.controller.js.map +1 -1
- package/dist/server/src/api/controllers/automations.controller.d.ts +17 -0
- package/dist/server/src/api/controllers/automations.controller.js +146 -0
- package/dist/server/src/api/controllers/automations.controller.js.map +1 -0
- package/dist/server/src/api/controllers/backup.controller.js +0 -1
- package/dist/server/src/api/controllers/backup.controller.js.map +1 -1
- package/dist/server/src/api/controllers/cameras.controller.d.ts +14 -5
- package/dist/server/src/api/controllers/cameras.controller.js +490 -69
- package/dist/server/src/api/controllers/cameras.controller.js.map +1 -1
- package/dist/server/src/api/controllers/config.controller.d.ts +2 -2
- package/dist/server/src/api/controllers/config.controller.js +2 -2
- package/dist/server/src/api/controllers/config.controller.js.map +1 -1
- package/dist/server/src/api/controllers/download.controller.d.ts +7 -0
- package/dist/server/src/api/controllers/download.controller.js +12 -0
- package/dist/server/src/api/controllers/download.controller.js.map +1 -0
- package/dist/server/src/api/controllers/files.controller.js.map +1 -1
- package/dist/server/src/api/controllers/frameWorkers.controller.d.ts +1 -1
- package/dist/server/src/api/controllers/frameWorkers.controller.js +1 -1
- package/dist/server/src/api/controllers/frameWorkers.controller.js.map +1 -1
- package/dist/server/src/api/controllers/instances.controller.d.ts +15 -0
- package/dist/server/src/api/controllers/instances.controller.js +100 -0
- package/dist/server/src/api/controllers/instances.controller.js.map +1 -0
- package/dist/server/src/api/controllers/notifications.controller.d.ts +15 -0
- package/dist/server/src/api/controllers/notifications.controller.js +121 -0
- package/dist/server/src/api/controllers/notifications.controller.js.map +1 -0
- package/dist/server/src/api/controllers/oauthCallback.controller.d.ts +15 -0
- package/dist/server/src/api/controllers/oauthCallback.controller.js +53 -0
- package/dist/server/src/api/controllers/oauthCallback.controller.js.map +1 -0
- package/dist/server/src/api/controllers/plugins.controller.d.ts +5 -9
- package/dist/server/src/api/controllers/plugins.controller.js +129 -246
- package/dist/server/src/api/controllers/plugins.controller.js.map +1 -1
- package/dist/server/src/api/controllers/remote.controller.d.ts +27 -0
- package/dist/server/src/api/controllers/remote.controller.js +247 -0
- package/dist/server/src/api/controllers/remote.controller.js.map +1 -0
- package/dist/server/src/api/controllers/server.controller.d.ts +24 -0
- package/dist/server/src/api/controllers/server.controller.js +236 -0
- package/dist/server/src/api/controllers/server.controller.js.map +1 -0
- package/dist/server/src/api/controllers/shares.controller.d.ts +12 -0
- package/dist/server/src/api/controllers/shares.controller.js +121 -0
- package/dist/server/src/api/controllers/shares.controller.js.map +1 -0
- package/dist/server/src/api/controllers/tunnel.controller.d.ts +9 -0
- package/dist/server/src/api/controllers/tunnel.controller.js +39 -0
- package/dist/server/src/api/controllers/tunnel.controller.js.map +1 -0
- package/dist/server/src/api/controllers/users.controller.d.ts +2 -2
- package/dist/server/src/api/controllers/users.controller.js +11 -2
- package/dist/server/src/api/controllers/users.controller.js.map +1 -1
- package/dist/server/src/api/controllers/workers.controller.d.ts +14 -0
- package/dist/server/src/api/controllers/workers.controller.js +69 -0
- package/dist/server/src/api/controllers/workers.controller.js.map +1 -0
- package/dist/server/src/api/database/checks.js +2 -2
- package/dist/server/src/api/database/checks.js.map +1 -1
- package/dist/server/src/api/database/constants.d.ts +10 -1
- package/dist/server/src/api/database/constants.js +10 -1
- package/dist/server/src/api/database/constants.js.map +1 -1
- package/dist/server/src/api/database/index.d.ts +24 -12
- package/dist/server/src/api/database/index.js +182 -126
- package/dist/server/src/api/database/index.js.map +1 -1
- package/dist/server/src/api/database/migration.d.ts +4 -13
- package/dist/server/src/api/database/migration.js +20 -80
- package/dist/server/src/api/database/migration.js.map +1 -1
- package/dist/server/src/api/database/migrations/index.d.ts +2 -0
- package/dist/server/src/api/database/migrations/index.js +24 -0
- package/dist/server/src/api/database/migrations/index.js.map +1 -0
- package/dist/server/src/api/database/migrations/types.d.ts +13 -0
- package/dist/server/src/api/database/migrations/types.js.map +1 -0
- package/dist/server/src/api/database/selfcheck.js +3 -0
- package/dist/server/src/api/database/selfcheck.js.map +1 -1
- package/dist/server/src/api/database/types.d.ts +173 -28
- package/dist/server/src/api/index.d.ts +8 -2
- package/dist/server/src/api/index.js +122 -43
- package/dist/server/src/api/index.js.map +1 -1
- package/dist/server/src/api/middlewares/authPermission.middleware.d.ts +4 -4
- package/dist/server/src/api/middlewares/authPermission.middleware.js +8 -8
- package/dist/server/src/api/middlewares/authPermission.middleware.js.map +1 -1
- package/dist/server/src/api/middlewares/authValidation.middleware.d.ts +5 -2
- package/dist/server/src/api/middlewares/authValidation.middleware.js +75 -114
- package/dist/server/src/api/middlewares/authValidation.middleware.js.map +1 -1
- package/dist/server/src/api/middlewares/pagination.middleware.d.ts +1 -1
- package/dist/server/src/api/middlewares/pagination.middleware.js +2 -2
- package/dist/server/src/api/middlewares/pagination.middleware.js.map +1 -1
- package/dist/server/src/api/middlewares/socketAuth.middleware.d.ts +2 -2
- package/dist/server/src/api/middlewares/socketAuth.middleware.js +5 -4
- package/dist/server/src/api/middlewares/socketAuth.middleware.js.map +1 -1
- package/dist/server/src/api/plugins/header.plugin.js +1 -1
- package/dist/server/src/api/plugins/header.plugin.js.map +1 -1
- package/dist/server/src/api/plugins/logger.plugin.js +13 -10
- package/dist/server/src/api/plugins/logger.plugin.js.map +1 -1
- package/dist/server/src/api/plugins/proxy.plugin.js +76 -105
- package/dist/server/src/api/plugins/proxy.plugin.js.map +1 -1
- package/dist/server/src/api/plugins/system.plugin.js.map +1 -1
- package/dist/server/src/api/plugins/useragent.plugin.d.ts +2 -2
- package/dist/server/src/api/plugins/useragent.plugin.js +2 -2
- package/dist/server/src/api/plugins/useragent.plugin.js.map +1 -1
- package/dist/server/src/api/routes/api.routes.js +18 -2
- package/dist/server/src/api/routes/api.routes.js.map +1 -1
- package/dist/server/src/api/routes/auth.routes.js +131 -9
- package/dist/server/src/api/routes/auth.routes.js.map +1 -1
- package/dist/server/src/api/routes/automations.routes.d.ts +2 -0
- package/dist/server/src/api/routes/automations.routes.js +128 -0
- package/dist/server/src/api/routes/automations.routes.js.map +1 -0
- package/dist/server/src/api/routes/backup.routes.js +6 -0
- package/dist/server/src/api/routes/backup.routes.js.map +1 -1
- package/dist/server/src/api/routes/cameras.routes.js +346 -33
- package/dist/server/src/api/routes/cameras.routes.js.map +1 -1
- package/dist/server/src/api/routes/config.routes.js +26 -4
- package/dist/server/src/api/routes/config.routes.js.map +1 -1
- package/dist/server/src/api/routes/download.routes.d.ts +2 -0
- package/dist/server/src/api/routes/download.routes.js +16 -0
- package/dist/server/src/api/routes/download.routes.js.map +1 -0
- package/dist/server/src/api/routes/files.routes.js +7 -1
- package/dist/server/src/api/routes/files.routes.js.map +1 -1
- package/dist/server/src/api/routes/frameWorkers.routes.js +26 -4
- package/dist/server/src/api/routes/frameWorkers.routes.js.map +1 -1
- package/dist/server/src/api/routes/index.d.ts +1 -0
- package/dist/server/src/api/routes/index.js +23 -3
- package/dist/server/src/api/routes/index.js.map +1 -1
- package/dist/server/src/api/routes/instances.routes.d.ts +2 -0
- package/dist/server/src/api/routes/instances.routes.js +105 -0
- package/dist/server/src/api/routes/instances.routes.js.map +1 -0
- package/dist/server/src/api/routes/notifications.routes.d.ts +2 -0
- package/dist/server/src/api/routes/notifications.routes.js +102 -0
- package/dist/server/src/api/routes/notifications.routes.js.map +1 -0
- package/dist/server/src/api/routes/oauthCallback.routes.d.ts +2 -0
- package/dist/server/src/api/routes/oauthCallback.routes.js +17 -0
- package/dist/server/src/api/routes/oauthCallback.routes.js.map +1 -0
- package/dist/server/src/api/routes/plugins.routes.js +259 -95
- package/dist/server/src/api/routes/plugins.routes.js.map +1 -1
- package/dist/server/src/api/routes/remote.routes.d.ts +2 -0
- package/dist/server/src/api/routes/remote.routes.js +164 -0
- package/dist/server/src/api/routes/remote.routes.js.map +1 -0
- package/dist/server/src/api/routes/server.routes.d.ts +2 -0
- package/dist/server/src/api/routes/server.routes.js +130 -0
- package/dist/server/src/api/routes/server.routes.js.map +1 -0
- package/dist/server/src/api/routes/shares.routes.d.ts +2 -0
- package/dist/server/src/api/routes/shares.routes.js +71 -0
- package/dist/server/src/api/routes/shares.routes.js.map +1 -0
- package/dist/server/src/api/routes/tunnel.routes.d.ts +2 -0
- package/dist/server/src/api/routes/tunnel.routes.js +14 -0
- package/dist/server/src/api/routes/tunnel.routes.js.map +1 -0
- package/dist/server/src/api/routes/users.routes.js +92 -12
- package/dist/server/src/api/routes/users.routes.js.map +1 -1
- package/dist/server/src/api/routes/workers.routes.d.ts +2 -0
- package/dist/server/src/api/routes/workers.routes.js +71 -0
- package/dist/server/src/api/routes/workers.routes.js.map +1 -0
- package/dist/server/src/api/schemas/auth.schema.d.ts +35 -0
- package/dist/server/src/api/schemas/auth.schema.js +37 -0
- package/dist/server/src/api/schemas/auth.schema.js.map +1 -0
- package/dist/server/src/api/schemas/automations.schema.d.ts +151 -0
- package/dist/server/src/api/schemas/automations.schema.js +84 -0
- package/dist/server/src/api/schemas/automations.schema.js.map +1 -0
- package/dist/server/src/api/schemas/backup.schema.d.ts +15 -190
- package/dist/server/src/api/schemas/backup.schema.js +5 -23
- package/dist/server/src/api/schemas/backup.schema.js.map +1 -1
- package/dist/server/src/api/schemas/cameras.schema.d.ts +1062 -1647
- package/dist/server/src/api/schemas/cameras.schema.js +218 -49
- package/dist/server/src/api/schemas/cameras.schema.js.map +1 -1
- package/dist/server/src/api/schemas/common.schema.d.ts +7 -0
- package/dist/server/src/api/schemas/common.schema.js +7 -0
- package/dist/server/src/api/schemas/common.schema.js.map +1 -0
- package/dist/server/src/api/schemas/config.schema.d.ts +41 -79
- package/dist/server/src/api/schemas/config.schema.js +19 -1
- package/dist/server/src/api/schemas/config.schema.js.map +1 -1
- package/dist/server/src/api/schemas/download.schema.d.ts +5 -0
- package/dist/server/src/api/schemas/download.schema.js +5 -0
- package/dist/server/src/api/schemas/download.schema.js.map +1 -0
- package/dist/server/src/api/schemas/files.schema.d.ts +5 -0
- package/dist/server/src/api/schemas/files.schema.js +5 -0
- package/dist/server/src/api/schemas/files.schema.js.map +1 -0
- package/dist/server/src/api/schemas/frameWorkers.schema.d.ts +5 -0
- package/dist/server/src/api/schemas/frameWorkers.schema.js +5 -0
- package/dist/server/src/api/schemas/frameWorkers.schema.js.map +1 -0
- package/dist/server/src/api/schemas/go2rtc.schema.d.ts +90 -640
- package/dist/server/src/api/schemas/go2rtc.schema.js +1 -16
- package/dist/server/src/api/schemas/go2rtc.schema.js.map +1 -1
- package/dist/server/src/api/schemas/instances.schema.d.ts +23 -0
- package/dist/server/src/api/schemas/instances.schema.js +24 -0
- package/dist/server/src/api/schemas/instances.schema.js.map +1 -0
- package/dist/server/src/api/schemas/notifications.schema.d.ts +26 -0
- package/dist/server/src/api/schemas/notifications.schema.js +25 -0
- package/dist/server/src/api/schemas/notifications.schema.js.map +1 -0
- package/dist/server/src/api/schemas/oauthCallback.schema.d.ts +11 -0
- package/dist/server/src/api/schemas/oauthCallback.schema.js +10 -0
- package/dist/server/src/api/schemas/oauthCallback.schema.js.map +1 -0
- package/dist/server/src/api/schemas/plugins.schema.d.ts +62 -59
- package/dist/server/src/api/schemas/plugins.schema.js +54 -81
- package/dist/server/src/api/schemas/plugins.schema.js.map +1 -1
- package/dist/server/src/api/schemas/remote.schema.d.ts +44 -0
- package/dist/server/src/api/schemas/remote.schema.js +80 -0
- package/dist/server/src/api/schemas/remote.schema.js.map +1 -0
- package/dist/server/src/api/schemas/server.schema.d.ts +9 -0
- package/dist/server/src/api/schemas/server.schema.js +12 -0
- package/dist/server/src/api/schemas/server.schema.js.map +1 -0
- package/dist/server/src/api/schemas/shares.schema.d.ts +21 -0
- package/dist/server/src/api/schemas/shares.schema.js +22 -0
- package/dist/server/src/api/schemas/shares.schema.js.map +1 -0
- package/dist/server/src/api/schemas/storage.schema.d.ts +5 -15
- package/dist/server/src/api/schemas/users.schema.d.ts +294 -786
- package/dist/server/src/api/schemas/users.schema.js +76 -39
- package/dist/server/src/api/schemas/users.schema.js.map +1 -1
- package/dist/server/src/api/schemas/workers.schema.d.ts +14 -0
- package/dist/server/src/api/schemas/workers.schema.js +12 -0
- package/dist/server/src/api/schemas/workers.schema.js.map +1 -0
- package/dist/server/src/api/services/auth.service.d.ts +27 -17
- package/dist/server/src/api/services/auth.service.js +106 -134
- package/dist/server/src/api/services/auth.service.js.map +1 -1
- package/dist/server/src/api/services/automations.service.d.ts +24 -0
- package/dist/server/src/api/services/automations.service.js +157 -0
- package/dist/server/src/api/services/automations.service.js.map +1 -0
- package/dist/server/src/api/services/backup.service.js +0 -5
- package/dist/server/src/api/services/backup.service.js.map +1 -1
- package/dist/server/src/api/services/cameras.service.d.ts +28 -15
- package/dist/server/src/api/services/cameras.service.js +532 -305
- package/dist/server/src/api/services/cameras.service.js.map +1 -1
- package/dist/server/src/api/services/downloads.service.d.ts +9 -0
- package/dist/server/src/api/services/downloads.service.js +20 -0
- package/dist/server/src/api/services/downloads.service.js.map +1 -0
- package/dist/server/src/api/services/instances.service.d.ts +52 -0
- package/dist/server/src/api/services/instances.service.js +344 -0
- package/dist/server/src/api/services/instances.service.js.map +1 -0
- package/dist/server/src/api/services/notifications.service.d.ts +21 -0
- package/dist/server/src/api/services/notifications.service.js +48 -0
- package/dist/server/src/api/services/notifications.service.js.map +1 -0
- package/dist/server/src/api/services/plugins.service.js +31 -35
- package/dist/server/src/api/services/plugins.service.js.map +1 -1
- package/dist/server/src/api/services/remote.service.d.ts +35 -0
- package/dist/server/src/api/services/remote.service.js +207 -0
- package/dist/server/src/api/services/remote.service.js.map +1 -0
- package/dist/server/src/api/services/server.service.d.ts +15 -0
- package/dist/server/src/api/services/server.service.js +75 -0
- package/dist/server/src/api/services/server.service.js.map +1 -0
- package/dist/server/src/api/services/shares.service.d.ts +46 -0
- package/dist/server/src/api/services/shares.service.js +233 -0
- package/dist/server/src/api/services/shares.service.js.map +1 -0
- package/dist/server/src/api/services/twoFactor.service.d.ts +22 -0
- package/dist/server/src/api/services/twoFactor.service.js +81 -0
- package/dist/server/src/api/services/twoFactor.service.js.map +1 -0
- package/dist/server/src/api/services/users.service.d.ts +9 -5
- package/dist/server/src/api/services/users.service.js +157 -121
- package/dist/server/src/api/services/users.service.js.map +1 -1
- package/dist/server/src/api/services/workers.service.d.ts +5 -0
- package/dist/server/src/api/services/workers.service.js +19 -0
- package/dist/server/src/api/services/workers.service.js.map +1 -0
- package/dist/server/src/api/types/index.d.ts +350 -133
- package/dist/server/src/api/types/index.js +5 -4
- package/dist/server/src/api/types/index.js.map +1 -1
- package/dist/server/src/api/utils/cert.js +1 -1
- package/dist/server/src/api/utils/cert.js.map +1 -1
- package/dist/server/src/api/utils/encryption.d.ts +5 -0
- package/dist/server/src/api/utils/encryption.js +25 -0
- package/dist/server/src/api/utils/encryption.js.map +1 -0
- package/dist/server/src/api/utils/plugin.d.ts +4 -0
- package/dist/server/src/api/utils/plugin.js +8 -0
- package/dist/server/src/api/utils/plugin.js.map +1 -0
- package/dist/server/src/api/utils/regex.d.ts +3 -0
- package/dist/server/src/api/utils/regex.js +4 -0
- package/dist/server/src/api/utils/regex.js.map +1 -0
- package/dist/server/src/api/utils/upload.d.ts +3 -0
- package/dist/server/src/api/utils/upload.js +23 -0
- package/dist/server/src/api/utils/upload.js.map +1 -0
- package/dist/server/src/api/websocket/index.js +18 -16
- package/dist/server/src/api/websocket/index.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/cameras.d.ts +21 -0
- package/dist/server/src/api/websocket/nsp/cameras.js +152 -0
- package/dist/server/src/api/websocket/nsp/cameras.js.map +1 -0
- package/dist/server/src/api/websocket/nsp/logs.d.ts +1 -1
- package/dist/server/src/api/websocket/nsp/logs.js +65 -52
- package/dist/server/src/api/websocket/nsp/logs.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/main.d.ts +4 -1
- package/dist/server/src/api/websocket/nsp/main.js +29 -1
- package/dist/server/src/api/websocket/nsp/main.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/metrics.js +4 -4
- package/dist/server/src/api/websocket/nsp/metrics.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/notifications.d.ts +3 -3
- package/dist/server/src/api/websocket/nsp/notifications.js +10 -11
- package/dist/server/src/api/websocket/nsp/notifications.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/server.d.ts +4 -4
- package/dist/server/src/api/websocket/nsp/server.js +48 -27
- package/dist/server/src/api/websocket/nsp/server.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/status.d.ts +3 -3
- package/dist/server/src/api/websocket/nsp/status.js +3 -3
- package/dist/server/src/api/websocket/nsp/status.js.map +1 -1
- package/dist/server/src/api/websocket/nsp/workers.d.ts +17 -0
- package/dist/server/src/api/websocket/nsp/workers.js +46 -0
- package/dist/server/src/api/websocket/nsp/workers.js.map +1 -0
- package/dist/server/src/api/websocket/types.d.ts +2 -1
- package/dist/server/src/api.d.ts +11 -16
- package/dist/server/src/api.js +62 -48
- package/dist/server/src/api.js.map +1 -1
- package/dist/server/src/automations/actions/cameraControl.d.ts +2 -0
- package/dist/server/src/automations/actions/cameraControl.js +35 -0
- package/dist/server/src/automations/actions/cameraControl.js.map +1 -0
- package/dist/server/src/automations/actions/delay.d.ts +2 -0
- package/dist/server/src/automations/actions/delay.js +8 -0
- package/dist/server/src/automations/actions/delay.js.map +1 -0
- package/dist/server/src/automations/actions/http.d.ts +2 -0
- package/dist/server/src/automations/actions/http.js +44 -0
- package/dist/server/src/automations/actions/http.js.map +1 -0
- package/dist/server/src/automations/actions/index.d.ts +4 -0
- package/dist/server/src/automations/actions/index.js +20 -0
- package/dist/server/src/automations/actions/index.js.map +1 -0
- package/dist/server/src/automations/actions/notification.d.ts +2 -0
- package/dist/server/src/automations/actions/notification.js +76 -0
- package/dist/server/src/automations/actions/notification.js.map +1 -0
- package/dist/server/src/automations/actions/plugin.d.ts +3 -0
- package/dist/server/src/automations/actions/plugin.js +73 -0
- package/dist/server/src/automations/actions/plugin.js.map +1 -0
- package/dist/server/src/automations/actions/sensor.d.ts +2 -0
- package/dist/server/src/automations/actions/sensor.js +17 -0
- package/dist/server/src/automations/actions/sensor.js.map +1 -0
- package/dist/server/src/automations/actions/snapshot.d.ts +2 -0
- package/dist/server/src/automations/actions/snapshot.js +20 -0
- package/dist/server/src/automations/actions/snapshot.js.map +1 -0
- package/dist/server/src/automations/actions/types.d.ts +14 -0
- package/dist/server/src/automations/actions/types.js.map +1 -0
- package/dist/server/src/automations/actions/variable.d.ts +2 -0
- package/dist/server/src/automations/actions/variable.js +17 -0
- package/dist/server/src/automations/actions/variable.js.map +1 -0
- package/dist/server/src/automations/conditions/ifelse.d.ts +3 -0
- package/dist/server/src/automations/conditions/ifelse.js +39 -0
- package/dist/server/src/automations/conditions/ifelse.js.map +1 -0
- package/dist/server/src/automations/conditions/index.d.ts +4 -0
- package/dist/server/src/automations/conditions/index.js +20 -0
- package/dist/server/src/automations/conditions/index.js.map +1 -0
- package/dist/server/src/automations/conditions/sensorState.d.ts +3 -0
- package/dist/server/src/automations/conditions/sensorState.js +21 -0
- package/dist/server/src/automations/conditions/sensorState.js.map +1 -0
- package/dist/server/src/automations/conditions/switch.d.ts +3 -0
- package/dist/server/src/automations/conditions/switch.js +9 -0
- package/dist/server/src/automations/conditions/switch.js.map +1 -0
- package/dist/server/src/automations/conditions/time.d.ts +3 -0
- package/dist/server/src/automations/conditions/time.js +24 -0
- package/dist/server/src/automations/conditions/time.js.map +1 -0
- package/dist/server/src/automations/conditions/types.d.ts +7 -0
- package/dist/server/src/automations/conditions/types.js.map +1 -0
- package/dist/server/src/automations/context.d.ts +48 -0
- package/dist/server/src/automations/context.js +146 -0
- package/dist/server/src/automations/context.js.map +1 -0
- package/dist/server/src/automations/engine.d.ts +35 -0
- package/dist/server/src/automations/engine.js +321 -0
- package/dist/server/src/automations/engine.js.map +1 -0
- package/dist/server/src/automations/haversine.d.ts +1 -0
- package/dist/server/src/automations/haversine.js +9 -0
- package/dist/server/src/automations/haversine.js.map +1 -0
- package/dist/server/src/automations/parseValue.d.ts +1 -0
- package/dist/server/src/automations/parseValue.js +11 -0
- package/dist/server/src/automations/parseValue.js.map +1 -0
- package/dist/server/src/automations/pluginMethodRegistry.d.ts +37 -0
- package/dist/server/src/automations/pluginMethodRegistry.js +162 -0
- package/dist/server/src/automations/pluginMethodRegistry.js.map +1 -0
- package/dist/server/src/automations/runner.d.ts +23 -0
- package/dist/server/src/automations/runner.js +166 -0
- package/dist/server/src/automations/runner.js.map +1 -0
- package/dist/server/src/automations/triggers/detection.d.ts +3 -0
- package/dist/server/src/automations/triggers/detection.js +102 -0
- package/dist/server/src/automations/triggers/detection.js.map +1 -0
- package/dist/server/src/automations/triggers/geofence.d.ts +13 -0
- package/dist/server/src/automations/triggers/geofence.js +8 -0
- package/dist/server/src/automations/triggers/geofence.js.map +1 -0
- package/dist/server/src/automations/triggers/index.d.ts +9 -0
- package/dist/server/src/automations/triggers/index.js +7 -0
- package/dist/server/src/automations/triggers/index.js.map +1 -0
- package/dist/server/src/automations/triggers/schedule.d.ts +3 -0
- package/dist/server/src/automations/triggers/schedule.js +54 -0
- package/dist/server/src/automations/triggers/schedule.js.map +1 -0
- package/dist/server/src/automations/triggers/sensor.d.ts +3 -0
- package/dist/server/src/automations/triggers/sensor.js +44 -0
- package/dist/server/src/automations/triggers/sensor.js.map +1 -0
- package/dist/server/src/automations/triggers/system.d.ts +3 -0
- package/dist/server/src/automations/triggers/system.js +31 -0
- package/dist/server/src/automations/triggers/system.js.map +1 -0
- package/dist/server/src/automations/triggers/types.d.ts +12 -0
- package/dist/server/src/automations/triggers/types.js.map +1 -0
- package/dist/server/src/automations/triggers/webhook.d.ts +7 -0
- package/dist/server/src/automations/triggers/webhook.js +8 -0
- package/dist/server/src/automations/triggers/webhook.js.map +1 -0
- package/dist/server/src/automations/utilities/imageInput.d.ts +2 -0
- package/dist/server/src/automations/utilities/imageInput.js +139 -0
- package/dist/server/src/automations/utilities/imageInput.js.map +1 -0
- package/dist/server/src/automations/utilities/index.d.ts +2 -0
- package/dist/server/src/automations/utilities/index.js +7 -0
- package/dist/server/src/automations/utilities/index.js.map +1 -0
- package/dist/server/src/automations/utilities/output.d.ts +2 -0
- package/dist/server/src/automations/utilities/output.js +10 -0
- package/dist/server/src/automations/utilities/output.js.map +1 -0
- package/dist/server/src/camera/controller.d.ts +56 -45
- package/dist/server/src/camera/controller.js +468 -326
- package/dist/server/src/camera/controller.js.map +1 -1
- package/dist/server/src/camera/decoder/audio-source.d.ts +34 -0
- package/dist/server/src/camera/decoder/audio-source.js +170 -0
- package/dist/server/src/camera/decoder/audio-source.js.map +1 -0
- package/dist/server/src/camera/decoder/cascade-manager.d.ts +22 -0
- package/dist/server/src/camera/decoder/cascade-manager.js +82 -0
- package/dist/server/src/camera/decoder/cascade-manager.js.map +1 -0
- package/dist/server/src/camera/decoder/child.d.ts +28 -0
- package/dist/server/src/camera/decoder/child.js +187 -0
- package/dist/server/src/camera/decoder/child.js.map +1 -0
- package/dist/server/src/camera/decoder/detection-coordinator.d.ts +142 -0
- package/dist/server/src/camera/decoder/detection-coordinator.js +1844 -0
- package/dist/server/src/camera/decoder/detection-coordinator.js.map +1 -0
- package/dist/server/src/camera/decoder/detection-pipeline.d.ts +41 -0
- package/dist/server/src/camera/decoder/detection-pipeline.js +216 -0
- package/dist/server/src/camera/decoder/detection-pipeline.js.map +1 -0
- package/dist/server/src/camera/decoder/dwell-manager.d.ts +23 -0
- package/dist/server/src/camera/decoder/dwell-manager.js +82 -0
- package/dist/server/src/camera/decoder/dwell-manager.js.map +1 -0
- package/dist/server/src/camera/decoder/event-manager.d.ts +97 -0
- package/dist/server/src/camera/decoder/event-manager.js +674 -0
- package/dist/server/src/camera/decoder/event-manager.js.map +1 -0
- package/dist/server/src/camera/decoder/frame-scaler.d.ts +53 -0
- package/dist/server/src/camera/decoder/frame-scaler.js +136 -0
- package/dist/server/src/camera/decoder/frame-scaler.js.map +1 -0
- package/dist/server/src/camera/decoder/frame-source.d.ts +54 -0
- package/dist/server/src/camera/decoder/frame-source.js +341 -0
- package/dist/server/src/camera/decoder/frame-source.js.map +1 -0
- package/dist/server/src/camera/decoder/ptz-autotracker.d.ts +57 -0
- package/dist/server/src/camera/decoder/ptz-autotracker.js +369 -0
- package/dist/server/src/camera/decoder/ptz-autotracker.js.map +1 -0
- package/dist/server/src/camera/decoder/types.d.ts +7 -0
- package/dist/server/src/camera/decoder/types.js +6 -0
- package/dist/server/src/camera/decoder/types.js.map +1 -0
- package/dist/server/src/camera/decoder/worker.d.ts +48 -0
- package/dist/server/src/camera/decoder/worker.js +465 -0
- package/dist/server/src/camera/decoder/worker.js.map +1 -0
- package/dist/server/src/camera/index.d.ts +43 -59
- package/dist/server/src/camera/index.js +72 -438
- package/dist/server/src/camera/index.js.map +1 -1
- package/dist/server/src/camera/sensors/controller.d.ts +96 -0
- package/dist/server/src/camera/sensors/controller.js +517 -0
- package/dist/server/src/camera/sensors/controller.js.map +1 -0
- package/dist/server/src/camera/sensors/sensor.d.ts +34 -0
- package/dist/server/src/camera/sensors/sensor.js +176 -0
- package/dist/server/src/camera/sensors/sensor.js.map +1 -0
- package/dist/server/src/camera/sensors/types.d.ts +27 -0
- package/dist/server/src/camera/sensors/types.js +225 -0
- package/dist/server/src/camera/sensors/types.js.map +1 -0
- package/dist/server/src/camera/streaming/fmp4-session.d.ts +10 -12
- package/dist/server/src/camera/streaming/fmp4-session.js +162 -268
- package/dist/server/src/camera/streaming/fmp4-session.js.map +1 -1
- package/dist/server/src/camera/streaming/rtp-session.d.ts +19 -0
- package/dist/server/src/camera/streaming/rtp-session.js +363 -0
- package/dist/server/src/camera/streaming/rtp-session.js.map +1 -0
- package/dist/server/src/camera/utils/filter.d.ts +6 -0
- package/dist/server/src/camera/utils/filter.js +83 -0
- package/dist/server/src/camera/utils/filter.js.map +1 -0
- package/dist/server/src/camera/utils.d.ts +2 -7
- package/dist/server/src/camera/utils.js +53 -194
- package/dist/server/src/camera/utils.js.map +1 -1
- package/dist/server/src/go2rtc/api/index.d.ts +16 -0
- package/dist/server/src/go2rtc/api/index.js +33 -0
- package/dist/server/src/go2rtc/api/index.js.map +1 -0
- package/dist/server/src/go2rtc/api/instance.d.ts +7 -0
- package/dist/server/src/go2rtc/api/instance.js +49 -0
- package/dist/server/src/go2rtc/api/instance.js.map +1 -0
- package/dist/server/src/go2rtc/api/manager.d.ts +11 -0
- package/dist/server/src/go2rtc/api/manager.js +38 -0
- package/dist/server/src/go2rtc/api/manager.js.map +1 -0
- package/dist/server/src/go2rtc/api/routes/application.d.ts +9 -0
- package/dist/server/src/go2rtc/api/routes/application.js +40 -0
- package/dist/server/src/go2rtc/api/routes/application.js.map +1 -0
- package/dist/server/src/go2rtc/api/routes/config.d.ts +8 -0
- package/dist/server/src/go2rtc/api/routes/config.js +42 -0
- package/dist/server/src/go2rtc/api/routes/config.js.map +1 -0
- package/dist/server/src/go2rtc/api/routes/discover.d.ts +30 -0
- package/dist/server/src/go2rtc/api/routes/discover.js +158 -0
- package/dist/server/src/go2rtc/api/routes/discover.js.map +1 -0
- package/dist/server/src/go2rtc/api/routes/snapshot.d.ts +8 -0
- package/dist/server/src/go2rtc/api/routes/snapshot.js +34 -0
- package/dist/server/src/go2rtc/api/routes/snapshot.js.map +1 -0
- package/dist/server/src/go2rtc/api/routes/streams.d.ts +18 -0
- package/dist/server/src/go2rtc/api/routes/streams.js +161 -0
- package/dist/server/src/go2rtc/api/routes/streams.js.map +1 -0
- package/dist/server/src/go2rtc/index.d.ts +7 -2
- package/dist/server/src/go2rtc/index.js +52 -30
- package/dist/server/src/go2rtc/index.js.map +1 -1
- package/dist/server/src/go2rtc/types.d.ts +167 -1
- package/dist/server/src/go2rtc/types.js +3 -0
- package/dist/server/src/go2rtc/types.js.map +1 -1
- package/dist/server/src/internal-bus.d.ts +41 -0
- package/dist/server/src/internal-bus.js +19 -0
- package/dist/server/src/internal-bus.js.map +1 -0
- package/dist/server/src/main.d.ts +8 -2
- package/dist/server/src/main.js +110 -21
- package/dist/server/src/main.js.map +1 -1
- package/dist/server/src/manager/coreManager.d.ts +12 -9
- package/dist/server/src/manager/coreManager.js +45 -48
- package/dist/server/src/manager/coreManager.js.map +1 -1
- package/dist/server/src/manager/deviceManager.d.ts +10 -8
- package/dist/server/src/manager/deviceManager.js +31 -96
- package/dist/server/src/manager/deviceManager.js.map +1 -1
- package/dist/server/src/manager/discoveryManager.d.ts +73 -0
- package/dist/server/src/manager/discoveryManager.js +800 -0
- package/dist/server/src/manager/discoveryManager.js.map +1 -0
- package/dist/server/src/manager/downloadManager.d.ts +27 -0
- package/dist/server/src/manager/downloadManager.js +353 -0
- package/dist/server/src/manager/downloadManager.js.map +1 -0
- package/dist/server/src/manager/notificationManager.d.ts +37 -0
- package/dist/server/src/manager/notificationManager.js +334 -0
- package/dist/server/src/manager/notificationManager.js.map +1 -0
- package/dist/server/src/manager/terminalManager.d.ts +27 -0
- package/dist/server/src/manager/terminalManager.js +239 -0
- package/dist/server/src/manager/terminalManager.js.map +1 -0
- package/dist/server/src/manager/types.d.ts +39 -14
- package/dist/server/src/manager/types.js +12 -1
- package/dist/server/src/manager/types.js.map +1 -1
- package/dist/server/src/plugins/index.d.ts +9 -6
- package/dist/server/src/plugins/index.js +69 -52
- package/dist/server/src/plugins/index.js.map +1 -1
- package/dist/server/src/plugins/plugin.d.ts +16 -16
- package/dist/server/src/plugins/plugin.js +42 -36
- package/dist/server/src/plugins/plugin.js.map +1 -1
- package/dist/server/src/plugins/runtime/base.d.ts +5 -14
- package/dist/server/src/plugins/runtime/base.js +39 -111
- package/dist/server/src/plugins/runtime/base.js.map +1 -1
- package/dist/server/src/plugins/runtime/go/index.d.ts +7 -0
- package/dist/server/src/plugins/runtime/go/index.js +110 -0
- package/dist/server/src/plugins/runtime/go/index.js.map +1 -0
- package/dist/server/src/plugins/runtime/index.js +5 -1
- package/dist/server/src/plugins/runtime/index.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/child.d.ts +7 -6
- package/dist/server/src/plugins/runtime/node/child.js +70 -38
- package/dist/server/src/plugins/runtime/node/child.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/index.d.ts +1 -0
- package/dist/server/src/plugins/runtime/node/index.js +31 -5
- package/dist/server/src/plugins/runtime/node/index.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/pluginApi.d.ts +9 -6
- package/dist/server/src/plugins/runtime/node/pluginApi.js +10 -4
- package/dist/server/src/plugins/runtime/node/pluginApi.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/proxy/cameraDevice.d.ts +27 -15
- package/dist/server/src/plugins/runtime/node/proxy/cameraDevice.js +312 -173
- package/dist/server/src/plugins/runtime/node/proxy/cameraDevice.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/proxy/coreManager.d.ts +7 -10
- package/dist/server/src/plugins/runtime/node/proxy/coreManager.js +28 -43
- package/dist/server/src/plugins/runtime/node/proxy/coreManager.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/proxy/deviceManager.d.ts +7 -11
- package/dist/server/src/plugins/runtime/node/proxy/deviceManager.js +40 -57
- package/dist/server/src/plugins/runtime/node/proxy/deviceManager.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/proxy/downloadManager.d.ts +9 -0
- package/dist/server/src/plugins/runtime/node/proxy/downloadManager.js +22 -0
- package/dist/server/src/plugins/runtime/node/proxy/downloadManager.js.map +1 -0
- package/dist/server/src/plugins/runtime/node/proxy/notificationManager.d.ts +7 -0
- package/dist/server/src/plugins/runtime/node/proxy/notificationManager.js +20 -0
- package/dist/server/src/plugins/runtime/node/proxy/notificationManager.js.map +1 -0
- package/dist/server/src/plugins/runtime/node/proxy/sensor.d.ts +45 -0
- package/dist/server/src/plugins/runtime/node/proxy/sensor.js +149 -0
- package/dist/server/src/plugins/runtime/node/proxy/sensor.js.map +1 -0
- package/dist/server/src/plugins/runtime/node/storage.d.ts +6 -11
- package/dist/server/src/plugins/runtime/node/storage.js +69 -46
- package/dist/server/src/plugins/runtime/node/storage.js.map +1 -1
- package/dist/server/src/plugins/runtime/node/storageController.d.ts +10 -7
- package/dist/server/src/plugins/runtime/node/storageController.js +57 -17
- package/dist/server/src/plugins/runtime/node/storageController.js.map +1 -1
- package/dist/server/src/plugins/runtime/python/camera/utils.py +105 -0
- package/dist/server/src/plugins/runtime/python/child.py +108 -68
- package/dist/server/src/plugins/runtime/python/index.js.map +1 -1
- package/dist/server/src/plugins/runtime/python/namespaces.py +155 -60
- package/dist/server/src/plugins/runtime/python/plugin_api.py +72 -6
- package/dist/server/src/plugins/runtime/python/proxy/camera_device.py +592 -1522
- package/dist/server/src/plugins/runtime/python/proxy/core_manager.py +75 -76
- package/dist/server/src/plugins/runtime/python/proxy/device_manager.py +81 -93
- package/dist/server/src/plugins/runtime/python/proxy/download_manager.py +33 -0
- package/dist/server/src/plugins/runtime/python/proxy/notification_manager.py +31 -0
- package/dist/server/src/plugins/runtime/python/proxy/sensor.py +169 -0
- package/dist/server/src/plugins/runtime/python/rpc/typings.py +56 -0
- package/dist/server/src/plugins/runtime/python/schema.py +54 -19
- package/dist/server/src/plugins/runtime/python/storage.py +84 -66
- package/dist/server/src/plugins/runtime/python/storage_controller.py +132 -38
- package/dist/server/src/plugins/runtime/python/typings.py +78 -152
- package/dist/server/src/plugins/schema.d.ts +27 -26
- package/dist/server/src/plugins/schema.js +183 -103
- package/dist/server/src/plugins/schema.js.map +1 -1
- package/dist/server/src/plugins/types.d.ts +2 -14
- package/dist/server/src/plugins/types.js +0 -1
- package/dist/server/src/plugins/types.js.map +1 -1
- package/dist/server/src/plugins/worker.d.ts +7 -7
- package/dist/server/src/plugins/worker.js +37 -26
- package/dist/server/src/plugins/worker.js.map +1 -1
- package/dist/server/src/remote/api/credentialStore.d.ts +18 -0
- package/dist/server/src/remote/api/credentialStore.js +101 -0
- package/dist/server/src/remote/api/credentialStore.js.map +1 -0
- package/dist/server/src/remote/api/index.d.ts +9 -0
- package/dist/server/src/remote/api/index.js +16 -0
- package/dist/server/src/remote/api/index.js.map +1 -0
- package/dist/server/src/remote/api/instance.d.ts +9 -0
- package/dist/server/src/remote/api/instance.js +44 -0
- package/dist/server/src/remote/api/instance.js.map +1 -0
- package/dist/server/src/remote/api/routes/oauth.d.ts +23 -0
- package/dist/server/src/remote/api/routes/oauth.js +79 -0
- package/dist/server/src/remote/api/routes/oauth.js.map +1 -0
- package/dist/server/src/remote/api/routes/server.d.ts +20 -0
- package/dist/server/src/remote/api/routes/server.js +58 -0
- package/dist/server/src/remote/api/routes/server.js.map +1 -0
- package/dist/server/src/remote/index.d.ts +25 -0
- package/dist/server/src/remote/index.js +70 -0
- package/dist/server/src/remote/index.js.map +1 -0
- package/dist/server/src/remote/push.d.ts +15 -0
- package/dist/server/src/remote/push.js +85 -0
- package/dist/server/src/remote/push.js.map +1 -0
- package/dist/server/src/remote/services/cloudflare-managed.d.ts +42 -0
- package/dist/server/src/remote/services/cloudflare-managed.js +284 -0
- package/dist/server/src/remote/services/cloudflare-managed.js.map +1 -0
- package/dist/server/src/remote/services/cloudflare.d.ts +38 -0
- package/dist/server/src/remote/services/cloudflare.js +232 -0
- package/dist/server/src/remote/services/cloudflare.js.map +1 -0
- package/dist/server/src/remote/services/customDomain.d.ts +9 -0
- package/dist/server/src/remote/services/customDomain.js +40 -0
- package/dist/server/src/remote/services/customDomain.js.map +1 -0
- package/dist/server/src/remote/services/index.d.ts +43 -0
- package/dist/server/src/remote/services/index.js +285 -0
- package/dist/server/src/remote/services/index.js.map +1 -0
- package/dist/server/src/remote/services/upnp.js +2 -0
- package/dist/server/src/remote/services/upnp.js.map +1 -0
- package/dist/server/src/remote/tunnel/client.d.ts +38 -0
- package/dist/server/src/remote/tunnel/client.js +241 -0
- package/dist/server/src/remote/tunnel/client.js.map +1 -0
- package/dist/server/src/remote/tunnel/index.d.ts +15 -0
- package/dist/server/src/remote/tunnel/index.js +68 -0
- package/dist/server/src/remote/tunnel/index.js.map +1 -0
- package/dist/server/src/remote/types.d.ts +31 -0
- package/dist/server/src/remote/types.js +2 -0
- package/dist/server/src/remote/types.js.map +1 -0
- package/dist/server/src/rpc/index.d.ts +24 -25
- package/dist/server/src/rpc/index.js +93 -77
- package/dist/server/src/rpc/index.js.map +1 -1
- package/dist/server/src/rpc/interfaces/config.d.ts +74 -0
- package/dist/server/src/rpc/interfaces/config.js +2 -0
- package/dist/server/src/rpc/interfaces/config.js.map +1 -0
- package/dist/server/src/rpc/interfaces/core.d.ts +25 -0
- package/dist/server/src/rpc/interfaces/core.js +2 -0
- package/dist/server/src/rpc/interfaces/core.js.map +1 -0
- package/dist/server/src/rpc/interfaces/detection.d.ts +70 -0
- package/dist/server/src/rpc/interfaces/detection.js +2 -0
- package/dist/server/src/rpc/interfaces/detection.js.map +1 -0
- package/dist/server/src/rpc/interfaces/device.d.ts +62 -0
- package/dist/server/src/rpc/interfaces/device.js +2 -0
- package/dist/server/src/rpc/interfaces/device.js.map +1 -0
- package/dist/server/src/rpc/interfaces/discovery.d.ts +46 -0
- package/dist/server/src/rpc/interfaces/discovery.js +2 -0
- package/dist/server/src/rpc/interfaces/discovery.js.map +1 -0
- package/dist/server/src/rpc/interfaces/download.d.ts +22 -0
- package/dist/server/src/rpc/interfaces/download.js +2 -0
- package/dist/server/src/rpc/interfaces/download.js.map +1 -0
- package/dist/server/src/rpc/interfaces/frameworker.d.ts +12 -0
- package/dist/server/src/rpc/interfaces/frameworker.js +2 -0
- package/dist/server/src/rpc/interfaces/frameworker.js.map +1 -0
- package/dist/server/src/rpc/interfaces/notification.d.ts +6 -0
- package/dist/server/src/rpc/interfaces/notification.js +2 -0
- package/dist/server/src/rpc/interfaces/notification.js.map +1 -0
- package/dist/server/src/rpc/interfaces/sensor.d.ts +75 -0
- package/dist/server/src/rpc/interfaces/sensor.js +2 -0
- package/dist/server/src/rpc/interfaces/sensor.js.map +1 -0
- package/dist/server/src/rpc/interfaces/terminal.d.ts +34 -0
- package/dist/server/src/rpc/interfaces/terminal.js +2 -0
- package/dist/server/src/rpc/interfaces/terminal.js.map +1 -0
- package/dist/server/src/rpc/namespaces.d.ts +50 -2
- package/dist/server/src/rpc/namespaces.js +70 -4
- package/dist/server/src/rpc/namespaces.js.map +1 -1
- package/dist/server/src/rpc/server.d.ts +22 -3
- package/dist/server/src/rpc/server.js +110 -37
- package/dist/server/src/rpc/server.js.map +1 -1
- package/dist/server/src/rpc/utils.d.ts +2 -1
- package/dist/server/src/rpc/utils.js +8 -0
- package/dist/server/src/rpc/utils.js.map +1 -1
- package/dist/server/src/services/config/constants.d.ts +7 -1
- package/dist/server/src/services/config/constants.js +17 -2
- package/dist/server/src/services/config/constants.js.map +1 -1
- package/dist/server/src/services/config/defaults.js +3 -3
- package/dist/server/src/services/config/defaults.js.map +1 -1
- package/dist/server/src/services/config/index.d.ts +6 -43
- package/dist/server/src/services/config/index.js +56 -108
- package/dist/server/src/services/config/index.js.map +1 -1
- package/dist/server/src/services/config/types.d.ts +14 -2
- package/dist/server/src/services/config/types.js.map +1 -1
- package/dist/server/src/services/logger/index.d.ts +13 -11
- package/dist/server/src/services/logger/index.js +47 -50
- package/dist/server/src/services/logger/index.js.map +1 -1
- package/dist/server/src/services/logger/logManager.d.ts +35 -0
- package/dist/server/src/services/logger/logManager.js +196 -0
- package/dist/server/src/services/logger/logManager.js.map +1 -0
- package/dist/server/src/services/logger/transports/fileTransport.d.ts +34 -0
- package/dist/server/src/services/logger/transports/fileTransport.js +152 -0
- package/dist/server/src/services/logger/transports/fileTransport.js.map +1 -0
- package/dist/server/src/services/logger/transports/index.d.ts +1 -0
- package/dist/server/src/services/logger/transports/index.js +2 -0
- package/dist/server/src/services/logger/transports/index.js.map +1 -0
- package/dist/server/src/types.d.ts +3 -0
- package/dist/server/src/utils/camera.d.ts +4 -0
- package/dist/server/src/utils/camera.js +79 -0
- package/dist/server/src/utils/camera.js.map +1 -0
- package/dist/server/src/utils/env.js +8 -0
- package/dist/server/src/utils/env.js.map +1 -0
- package/dist/server/src/utils/ipc.d.ts +1 -1
- package/dist/server/src/utils/ipc.js +2 -2
- package/dist/server/src/utils/ipc.js.map +1 -1
- package/dist/server/src/utils/path.js +3 -3
- package/dist/server/src/utils/path.js.map +1 -1
- package/dist/server/src/utils/pythonInstaller.d.ts +2 -1
- package/dist/server/src/utils/pythonInstaller.js +6 -6
- package/dist/server/src/utils/pythonInstaller.js.map +1 -1
- package/dist/server/src/workers/agent.d.ts +27 -0
- package/dist/server/src/workers/agent.js +161 -0
- package/dist/server/src/workers/agent.js.map +1 -0
- package/dist/server/src/workers/capabilities/frame-decoding.d.ts +24 -0
- package/dist/server/src/workers/capabilities/frame-decoding.js +180 -0
- package/dist/server/src/workers/capabilities/frame-decoding.js.map +1 -0
- package/dist/server/src/workers/capabilities/handler.d.ts +8 -0
- package/dist/server/src/workers/capabilities/handler.js +2 -0
- package/dist/server/src/workers/capabilities/handler.js.map +1 -0
- package/dist/server/src/workers/manager.d.ts +31 -0
- package/dist/server/src/workers/manager.js +260 -0
- package/dist/server/src/workers/manager.js.map +1 -0
- package/dist/server/src/workers/types.d.ts +59 -0
- package/dist/server/src/workers/types.js +5 -0
- package/dist/server/src/workers/types.js.map +1 -0
- package/package.json +73 -79
- package/dist/interface/assets/@xterm.DYP7pi_n.0.0.69.css +0 -32
- package/dist/interface/assets/Adminpanel.BKek2EMH.0.0.69.css +0 -1
- package/dist/interface/assets/Cameras.BDWZJqPN.0.0.69.css +0 -1
- package/dist/interface/assets/Camview.Cvhuou6V.0.0.69.css +0 -1
- package/dist/interface/assets/CuiConsole.DCYyxdVg.0.0.69.css +0 -1
- package/dist/interface/assets/CuiPluginCard.yF8V0SZY.0.0.69.css +0 -1
- package/dist/interface/assets/CuiTimeline.BkIwlYtw.0.0.69.css +0 -1
- package/dist/interface/assets/Plugin.DJElsAn5.0.0.69.css +0 -1
- package/dist/interface/assets/Plugins.BwPlcRrV.0.0.69.css +0 -1
- package/dist/interface/assets/Settings.CkgfRkQr.0.0.69.css +0 -1
- package/dist/interface/assets/SettingsAccount.CDZT7gN-.0.0.69.css +0 -1
- package/dist/interface/assets/highlight.Ch2EwETz.0.0.69.css +0 -1
- package/dist/interface/assets/main.BmO7mnW4.0.0.69.css +0 -1
- package/dist/interface/assets/worker-base.jEXLGV2h.0.0.69.js +0 -1332
- package/dist/interface/assets/worker-yaml.B3uUYINB.0.0.69.js +0 -5819
- package/dist/interface/js/@babel.l0sNRNKZ.0.0.69.js +0 -1
- package/dist/interface/js/@intlify.6ljJeWIl.0.0.69.js +0 -15
- package/dist/interface/js/@kurkle.D8fDXNIl.0.0.69.js +0 -6
- package/dist/interface/js/@primeuix.bRNqZjQz.0.0.69.js +0 -5889
- package/dist/interface/js/@primevue.C5r50LKM.0.0.69.js +0 -57
- package/dist/interface/js/@react-dnd.CcwRs9xb.0.0.69.js +0 -1
- package/dist/interface/js/@socket.io.Dkula2eQ.0.0.69.js +0 -1
- package/dist/interface/js/@tanstack.ESyaYTt8.0.0.69.js +0 -1
- package/dist/interface/js/@vee-validate.CeUgfPaH.0.0.69.js +0 -5
- package/dist/interface/js/@vue.BsSvBeCe.0.0.69.js +0 -17
- package/dist/interface/js/@vueuse.NhwSnX_y.0.0.69.js +0 -1
- package/dist/interface/js/@xterm.DHnCBlz-.0.0.69.js +0 -66
- package/dist/interface/js/Adminpanel.CR_zSM68.0.0.69.js +0 -1
- package/dist/interface/js/Camera.Cc2GMAQz.0.0.69.js +0 -1
- package/dist/interface/js/Cameras.AVNvfmPx.0.0.69.js +0 -482
- package/dist/interface/js/Cammesh.6TFnt2Jx.0.0.69.js +0 -1
- package/dist/interface/js/Camview.CTs17jUK.0.0.69.js +0 -1
- package/dist/interface/js/Config.BcnTMnwK.0.0.69.js +0 -2
- package/dist/interface/js/Console.C2u30_a4.0.0.69.js +0 -4
- package/dist/interface/js/CuiConsole.C_vx3eur.0.0.69.js +0 -1
- package/dist/interface/js/CuiPluginCard.DXCSR91d.0.0.69.js +0 -4
- package/dist/interface/js/CuiTimeline.D24_kazZ.0.0.69.js +0 -1
- package/dist/interface/js/FirstSteps.DmFQyph_.0.0.69.js +0 -1
- package/dist/interface/js/Plugin.DnLoseHB.0.0.69.js +0 -1
- package/dist/interface/js/Plugins.D6nWkZe3.0.0.69.js +0 -1
- package/dist/interface/js/Recordings.BGcye9TW.0.0.69.js +0 -1
- package/dist/interface/js/Settings.CLR_jqKd.0.0.69.js +0 -1
- package/dist/interface/js/SettingsAccount.D9QAC8hM.0.0.69.js +0 -1
- package/dist/interface/js/SettingsAppearance.Dg_3Nbvy.0.0.69.js +0 -1
- package/dist/interface/js/SettingsAppearance.vue_vue_type_script_setup_true_lang.DZQvbT2Y.0.0.69.js +0 -1
- package/dist/interface/js/SettingsBackup.C35jy9a9.0.0.69.js +0 -1
- package/dist/interface/js/SettingsRecordings.C5na6ke4.0.0.69.js +0 -1
- package/dist/interface/js/SettingsRemote.BrU66scR.0.0.69.js +0 -1
- package/dist/interface/js/SettingsSystem.DmU4H9b1.0.0.69.js +0 -1
- package/dist/interface/js/SettingsUsers.DQN0jbzy.0.0.69.js +0 -1
- package/dist/interface/js/VersionsHandler.vue_vue_type_script_setup_true_lang.Cyp9Qkwy.0.0.69.js +0 -4
- package/dist/interface/js/ace-builds.D-7Qis2t.0.0.69.js +0 -1091
- package/dist/interface/js/ace.config.ButjQxKc.0.0.69.js +0 -1
- package/dist/interface/js/axios.lj9VQs0f.0.0.69.js +0 -6
- package/dist/interface/js/backup.ZVXbFg1K.0.0.69.js +0 -1
- package/dist/interface/js/birpc.l0sNRNKZ.0.0.69.js +0 -1
- package/dist/interface/js/chart.js.Dz1J8kd4.0.0.69.js +0 -13
- package/dist/interface/js/close-circle.DJNW4HfJ.0.0.69.js +0 -1
- package/dist/interface/js/compare-versions.DqEOhma6.0.0.69.js +0 -1
- package/dist/interface/js/dijkstrajs.C00ieaqj.0.0.69.js +0 -1
- package/dist/interface/js/dnd-core.D_qG7vz7.0.0.69.js +0 -1
- package/dist/interface/js/draggabilly.BoYjrLDK.0.0.69.js +0 -6
- package/dist/interface/js/engine.io-client.B5m3FsEv.0.0.69.js +0 -1
- package/dist/interface/js/engine.io-parser.BiEtp6m2.0.0.69.js +0 -1
- package/dist/interface/js/entities.C20TfXL6.0.0.69.js +0 -1
- package/dist/interface/js/ev-emitter.X5f1qa-c.0.0.69.js +0 -1
- package/dist/interface/js/fast-deep-equal.IL3J8jAG.0.0.69.js +0 -1
- package/dist/interface/js/get-size.D1dS-IaP.0.0.69.js +0 -5
- package/dist/interface/js/highlight.js.BSQb76p3.0.0.69.js +0 -3
- package/dist/interface/js/hookable.l0sNRNKZ.0.0.69.js +0 -1
- package/dist/interface/js/linkify-it.DggZxsPz.0.0.69.js +0 -1
- package/dist/interface/js/main.BNZUJnjG.0.0.69.js +0 -31
- package/dist/interface/js/markdown-it.MLL3O76W.0.0.69.js +0 -15
- package/dist/interface/js/mdurl.k9Sl0PQj.0.0.69.js +0 -2
- package/dist/interface/js/nprogress.BYU1Y2h8.0.0.69.js +0 -2
- package/dist/interface/js/perfect-debounce.l0sNRNKZ.0.0.69.js +0 -1
- package/dist/interface/js/pinia.xXUM0Drf.0.0.69.js +0 -5
- package/dist/interface/js/primelocale.Bga3dOQu.0.0.69.js +0 -1
- package/dist/interface/js/primevue.CYqFPO0y.0.0.69.js +0 -142
- package/dist/interface/js/punycode.js.Dj65hjkv.0.0.69.js +0 -1
- package/dist/interface/js/qrcode.D3FbUuTi.0.0.69.js +0 -8
- package/dist/interface/js/react-dnd-html5-backend.1HQjlkwI.0.0.69.js +0 -2
- package/dist/interface/js/react-dnd-touch-backend.ChJx6T3S.0.0.69.js +0 -1
- package/dist/interface/js/redux.BFxtlG_c.0.0.69.js +0 -1
- package/dist/interface/js/refresh-rounded.DLelUEXh.0.0.69.js +0 -1
- package/dist/interface/js/rxjs.AXKlNjX-.0.0.69.js +0 -3
- package/dist/interface/js/socket.io-client.NZWSNJlD.0.0.69.js +0 -1
- package/dist/interface/js/socket.io-parser.3CqTF9_v.0.0.69.js +0 -1
- package/dist/interface/js/system.AeO3hneo.0.0.69.js +0 -1
- package/dist/interface/js/trash-fill.CxzXm2nA.0.0.69.js +0 -1
- package/dist/interface/js/tslib.9k7AwCpt.0.0.69.js +0 -1
- package/dist/interface/js/uc.micro.kMc2yuuw.0.0.69.js +0 -1
- package/dist/interface/js/unidragger.UylmBmyV.0.0.69.js +0 -5
- package/dist/interface/js/uuid.C6aID195.0.0.69.js +0 -1
- package/dist/interface/js/vee-validate.CXzK59HL.0.0.69.js +0 -5
- package/dist/interface/js/vue-chartjs.Dr8dSHCc.0.0.69.js +0 -1
- package/dist/interface/js/vue-i18n.BsJO9RBQ.0.0.69.js +0 -5
- package/dist/interface/js/vue-inline-svg.1baioXR8.0.0.69.js +0 -1
- package/dist/interface/js/vue-router.Cnp23wAe.0.0.69.js +0 -5
- package/dist/interface/js/vue-zoomable.DMxVl9qH.0.0.69.js +0 -1
- package/dist/interface/js/vue.l0sNRNKZ.0.0.69.js +0 -1
- package/dist/interface/js/vue3-dnd.Cre7FigV.0.0.69.js +0 -1
- package/dist/interface/js/zod.2bfLsWMZ.0.0.69.js +0 -1
- package/dist/interface/js/zoom-out.BEqLMm84.0.0.69.js +0 -1
- package/dist/interface/registerSW.js +0 -1
- package/dist/interface/workbox-5ffe50d4.js +0 -1
- package/dist/server/src/_camera_ui_tools/camera_ui_common/camera_utils/utils.py +0 -52
- package/dist/server/src/_camera_ui_tools/camera_ui_common/logger_service/test.py +0 -116
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/__init__.py +0 -350
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/__init__.py +0 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/base.py +0 -237
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/client.py +0 -256
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/connection.py +0 -784
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/errors.py +0 -745
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/messaging.py +0 -57
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/rpc.py +0 -227
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/rpc_generator.py +0 -584
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/constants.py +0 -96
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/typings.py +0 -218
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/__init__.py +0 -0
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/connection_state.py +0 -86
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/logger.py +0 -30
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/metrics.py +0 -152
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/packer.py +0 -20
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/routing.py +0 -75
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/rpc.py +0 -177
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/subscriptions.py +0 -24
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/tasks.py +0 -39
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/uid.py +0 -37
- package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/validate.py +0 -119
- package/dist/server/src/_camera_ui_tools/camera_ui_types/__init__.py +0 -1369
- package/dist/server/src/_camera_ui_tools/camera_ui_types/hybrid_observer.py +0 -338
- package/dist/server/src/_camera_ui_tools/camera_ui_types/test.py +0 -196
- package/dist/server/src/api/controllers/system.controller.d.ts +0 -24
- package/dist/server/src/api/controllers/system.controller.js +0 -235
- package/dist/server/src/api/controllers/system.controller.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/application.d.ts +0 -9
- package/dist/server/src/api/go2rtc/api/application.js +0 -39
- package/dist/server/src/api/go2rtc/api/application.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/config.d.ts +0 -8
- package/dist/server/src/api/go2rtc/api/config.js +0 -44
- package/dist/server/src/api/go2rtc/api/config.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/discover.d.ts +0 -30
- package/dist/server/src/api/go2rtc/api/discover.js +0 -162
- package/dist/server/src/api/go2rtc/api/discover.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/index.d.ts +0 -1
- package/dist/server/src/api/go2rtc/api/index.js +0 -42
- package/dist/server/src/api/go2rtc/api/index.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/snapshot.d.ts +0 -8
- package/dist/server/src/api/go2rtc/api/snapshot.js +0 -34
- package/dist/server/src/api/go2rtc/api/snapshot.js.map +0 -1
- package/dist/server/src/api/go2rtc/api/streams.d.ts +0 -20
- package/dist/server/src/api/go2rtc/api/streams.js +0 -190
- package/dist/server/src/api/go2rtc/api/streams.js.map +0 -1
- package/dist/server/src/api/go2rtc/index.d.ts +0 -16
- package/dist/server/src/api/go2rtc/index.js +0 -33
- package/dist/server/src/api/go2rtc/index.js.map +0 -1
- package/dist/server/src/api/go2rtc/queue.d.ts +0 -10
- package/dist/server/src/api/go2rtc/queue.js +0 -38
- package/dist/server/src/api/go2rtc/queue.js.map +0 -1
- package/dist/server/src/api/go2rtc/types.d.ts +0 -151
- package/dist/server/src/api/go2rtc/types.js.map +0 -1
- package/dist/server/src/api/routes/system.routes.d.ts +0 -2
- package/dist/server/src/api/routes/system.routes.js +0 -86
- package/dist/server/src/api/routes/system.routes.js.map +0 -1
- package/dist/server/src/api/schemas/system.schema.d.ts +0 -185
- package/dist/server/src/api/schemas/system.schema.js +0 -40
- package/dist/server/src/api/schemas/system.schema.js.map +0 -1
- package/dist/server/src/api/services/system.service.d.ts +0 -13
- package/dist/server/src/api/services/system.service.js +0 -63
- package/dist/server/src/api/services/system.service.js.map +0 -1
- package/dist/server/src/camera/classes.d.ts +0 -2
- package/dist/server/src/camera/classes.js +0 -24
- package/dist/server/src/camera/classes.js.map +0 -1
- package/dist/server/src/camera/device.d.ts +0 -34
- package/dist/server/src/camera/device.js +0 -327
- package/dist/server/src/camera/device.js.map +0 -1
- package/dist/server/src/camera/frameWorker.d.ts +0 -46
- package/dist/server/src/camera/frameWorker.js +0 -347
- package/dist/server/src/camera/frameWorker.js.map +0 -1
- package/dist/server/src/camera/interfaces.d.ts +0 -17
- package/dist/server/src/camera/interfaces.js +0 -99
- package/dist/server/src/camera/interfaces.js.map +0 -1
- package/dist/server/src/camera/iou.d.ts +0 -2
- package/dist/server/src/camera/iou.js +0 -122
- package/dist/server/src/camera/iou.js.map +0 -1
- package/dist/server/src/camera/polygon.d.ts +0 -4
- package/dist/server/src/camera/polygon.js +0 -192
- package/dist/server/src/camera/polygon.js.map +0 -1
- package/dist/server/src/camera/python/__init__.py +0 -0
- package/dist/server/src/camera/python/classes.py +0 -41
- package/dist/server/src/camera/python/interfaces.py +0 -131
- package/dist/server/src/camera/python/iou.py +0 -158
- package/dist/server/src/camera/python/polygon.py +0 -230
- package/dist/server/src/camera/python/typings.py +0 -50
- package/dist/server/src/camera/python/video_frame.py +0 -143
- package/dist/server/src/camera/streaming/peer-connection.d.ts +0 -26
- package/dist/server/src/camera/streaming/peer-connection.js +0 -213
- package/dist/server/src/camera/streaming/peer-connection.js.map +0 -1
- package/dist/server/src/camera/streaming/rtsp-session.d.ts +0 -19
- package/dist/server/src/camera/streaming/rtsp-session.js +0 -196
- package/dist/server/src/camera/streaming/rtsp-session.js.map +0 -1
- package/dist/server/src/camera/streaming/webrtc-connection.d.ts +0 -44
- package/dist/server/src/camera/streaming/webrtc-connection.js +0 -177
- package/dist/server/src/camera/streaming/webrtc-connection.js.map +0 -1
- package/dist/server/src/camera/streaming/werift-session.d.ts +0 -19
- package/dist/server/src/camera/streaming/werift-session.js +0 -246
- package/dist/server/src/camera/streaming/werift-session.js.map +0 -1
- package/dist/server/src/camera/types.d.ts +0 -17
- package/dist/server/src/camera/types.js.map +0 -1
- package/dist/server/src/camera/videoFrame.d.ts +0 -18
- package/dist/server/src/camera/videoFrame.js +0 -88
- package/dist/server/src/camera/videoFrame.js.map +0 -1
- package/dist/server/src/cloud/index.d.ts +0 -12
- package/dist/server/src/cloud/index.js +0 -49
- package/dist/server/src/cloud/index.js.map +0 -1
- package/dist/server/src/cloud/remote/cloudflare.d.ts +0 -7
- package/dist/server/src/cloud/remote/cloudflare.js +0 -12
- package/dist/server/src/cloud/remote/cloudflare.js.map +0 -1
- package/dist/server/src/cloud/remote/upnp.d.ts +0 -7
- package/dist/server/src/cloud/remote/upnp.js +0 -12
- package/dist/server/src/cloud/remote/upnp.js.map +0 -1
- package/dist/server/src/cloud/remote/utils.d.ts +0 -3
- package/dist/server/src/cloud/remote/utils.js +0 -21
- package/dist/server/src/cloud/remote/utils.js.map +0 -1
- package/dist/server/src/cloud/types.d.ts +0 -15
- package/dist/server/src/cloud/types.js +0 -11
- package/dist/server/src/cloud/types.js.map +0 -1
- package/dist/server/src/decoder/child.js +0 -748
- package/dist/server/src/decoder/child.js.map +0 -1
- package/dist/server/src/decoder/imageUtils.d.ts +0 -21
- package/dist/server/src/decoder/imageUtils.js +0 -204
- package/dist/server/src/decoder/imageUtils.js.map +0 -1
- package/dist/server/src/decoder/manager.d.ts +0 -19
- package/dist/server/src/decoder/manager.js +0 -208
- package/dist/server/src/decoder/manager.js.map +0 -1
- package/dist/server/src/decoder/python/__init__.py +0 -0
- package/dist/server/src/decoder/python/child.py +0 -902
- package/dist/server/src/decoder/python/image_utils.py +0 -196
- package/dist/server/src/decoder/python/pool.py +0 -45
- package/dist/server/src/decoder/python/typings.py +0 -57
- package/dist/server/src/decoder/python/utils.py +0 -70
- package/dist/server/src/decoder/types.d.ts +0 -23
- package/dist/server/src/decoder/types.js.map +0 -1
- package/dist/server/src/decoder/utils.d.ts +0 -13
- package/dist/server/src/decoder/utils.js +0 -45
- package/dist/server/src/decoder/utils.js.map +0 -1
- package/dist/server/src/decoder/wasm/build/decoder.d.ts +0 -43
- package/dist/server/src/decoder/wasm/build/decoder.js +0 -108
- package/dist/server/src/decoder/wasm/build/decoder.wasm +0 -0
- package/dist/server/src/decoder/worker.js +0 -79
- package/dist/server/src/decoder/worker.js.map +0 -1
- package/dist/server/src/plugins/runtime/node/plugin.d.ts +0 -24
- package/dist/server/src/plugins/runtime/node/plugin.js +0 -128
- package/dist/server/src/plugins/runtime/node/plugin.js.map +0 -1
- package/dist/server/src/plugins/runtime/python/plugin.py +0 -155
- package/dist/server/src/rpc/types.d.ts +0 -112
- package/dist/server/src/rpc/types.js.map +0 -1
- /package/dist/interface/assets/{SettingsBackup.CX0rT0QJ.0.0.69.css → SettingsBackup-CX0rT0QJ.css} +0 -0
- /package/dist/interface/assets/{logo-512.DLKVOU2S.0.0.69.png → error-256-DLKVOU2S.png} +0 -0
- /package/dist/interface/assets/{logo-256.BCQk9H1-.0.0.69.png → logo-256-BCQk9H1-.png} +0 -0
- /package/dist/interface/assets/{logo.DmEiRk0z.0.0.69.png → logo-DmEiRk0z.png} +0 -0
- /package/dist/interface/assets/{mode-yaml.CIYL8U3d.0.0.69.js → mode-yaml-CIYL8U3d.js} +0 -0
- /package/dist/server/src/api/{go2rtc → database/migrations}/types.js +0 -0
- /package/dist/server/src/{camera → automations/actions}/types.js +0 -0
- /package/dist/server/src/{decoder → automations/conditions}/types.js +0 -0
- /package/dist/server/src/{rpc → automations/triggers}/types.js +0 -0
- /package/dist/server/src/{decoder/child.d.ts → remote/services/upnp.d.ts} +0 -0
- /package/dist/server/src/{decoder/worker.d.ts → utils/env.d.ts} +0 -0
|
@@ -0,0 +1,1694 @@
|
|
|
1
|
+
"""RPC Client implementation."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import contextlib
|
|
5
|
+
import ssl
|
|
6
|
+
import traceback
|
|
7
|
+
from collections.abc import AsyncGenerator, Awaitable, Callable, Coroutine
|
|
8
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
9
|
+
from functools import partial
|
|
10
|
+
from typing import Any, Generic, Literal, TypeVar, cast, overload
|
|
11
|
+
|
|
12
|
+
from nats import (
|
|
13
|
+
connect, # pyright: ignore[reportUnknownVariableType]
|
|
14
|
+
errors,
|
|
15
|
+
)
|
|
16
|
+
from nats.aio.client import NO_RESPONDERS_STATUS
|
|
17
|
+
from nats.aio.client import Client as NATSClient
|
|
18
|
+
from nats.aio.msg import Msg
|
|
19
|
+
from nats.aio.subscription import Subscription
|
|
20
|
+
from nats.js.api import Header
|
|
21
|
+
|
|
22
|
+
from .channel import Channel, PrivateChannel
|
|
23
|
+
from .chunking import ChunkingManager, create_chunks
|
|
24
|
+
from .codec import decode, encode
|
|
25
|
+
from .decorators import extract_nested_methods_with_decorators, extract_nested_methods_without_decorators
|
|
26
|
+
from .errors import RPCException, create_error
|
|
27
|
+
from .executor import get_executor
|
|
28
|
+
from .handler import (
|
|
29
|
+
format_error_dict,
|
|
30
|
+
handle_callback_request,
|
|
31
|
+
handle_normal_rpc,
|
|
32
|
+
handle_pull_callback_request,
|
|
33
|
+
handle_pull_iterator_request,
|
|
34
|
+
handle_stream_request,
|
|
35
|
+
)
|
|
36
|
+
from .service import RPCService
|
|
37
|
+
from .types import (
|
|
38
|
+
CallbackParams,
|
|
39
|
+
ChunkedTransferHeader,
|
|
40
|
+
ConnectionOptions,
|
|
41
|
+
ErrorCode,
|
|
42
|
+
NoResponderRetryOptions,
|
|
43
|
+
PullCallbackParams,
|
|
44
|
+
PullIteratorRequest,
|
|
45
|
+
PullIteratorResponse,
|
|
46
|
+
RPCAuthOptions,
|
|
47
|
+
RPCClientOptions,
|
|
48
|
+
RPCError,
|
|
49
|
+
RPCMessage,
|
|
50
|
+
RPCResponse,
|
|
51
|
+
StreamMessage,
|
|
52
|
+
)
|
|
53
|
+
from .types import ProxyWithClose as ProxyWithCloseProtocol
|
|
54
|
+
from .types import RPCClient as RPCClientProtocol
|
|
55
|
+
from .utils import create_proxy, create_service_proxy, generate_id, is_async_function
|
|
56
|
+
|
|
57
|
+
T = TypeVar("T")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def create_rpc_client(options: RPCClientOptions) -> RPCClientProtocol:
|
|
61
|
+
"""Create a new RPC client instance."""
|
|
62
|
+
return RPCClient(options)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ProxyWithClose(Generic[T], ProxyWithCloseProtocol[T]):
|
|
66
|
+
def __init__(self, proxy: T) -> None:
|
|
67
|
+
self._proxy: T = proxy
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def proxy(self) -> T:
|
|
71
|
+
return self._proxy
|
|
72
|
+
|
|
73
|
+
async def close(self) -> None:
|
|
74
|
+
isolated_client = cast(RPCClient | None, getattr(self.proxy, "_isolated_client", None))
|
|
75
|
+
if isolated_client:
|
|
76
|
+
await isolated_client.disconnect()
|
|
77
|
+
# Remove from parent's tracked list if still present
|
|
78
|
+
parent = cast(RPCClient | None, getattr(self.proxy, "_parent_client", None))
|
|
79
|
+
if parent and isolated_client in parent.isolated_clients:
|
|
80
|
+
parent.isolated_clients.remove(isolated_client)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class RPCClient(RPCClientProtocol):
|
|
84
|
+
"""RPC client for NATS-based communication."""
|
|
85
|
+
|
|
86
|
+
def __init__(self, options: RPCClientOptions):
|
|
87
|
+
"""Initialize RPC client with options."""
|
|
88
|
+
self.options: RPCClientOptions = options
|
|
89
|
+
self.service: RPCService = RPCService(cast(Any, self))
|
|
90
|
+
|
|
91
|
+
self.nc: NATSClient | None = None
|
|
92
|
+
self.subscriptions: dict[str, list[Subscription]] = {}
|
|
93
|
+
self.chunking_manager: ChunkingManager = ChunkingManager()
|
|
94
|
+
self._max_payload_size: int = 1024 * 1024 # Default 1MB
|
|
95
|
+
self._connection_task: asyncio.Task[NATSClient] | None = None
|
|
96
|
+
|
|
97
|
+
self.pending_requests: dict[str, dict[str, Any]] = {}
|
|
98
|
+
self.stream_handlers: dict[str, dict[str, Any]] = {}
|
|
99
|
+
self.isolated_clients: list[RPCClient] = []
|
|
100
|
+
self.pull_iterator_cleanups: dict[str, Callable[[], Coroutine[Any, Any, None]]] = {}
|
|
101
|
+
self.callback_cleanups: dict[str, Callable[[], Coroutine[Any, Any, None]]] = {}
|
|
102
|
+
|
|
103
|
+
self._closed = False
|
|
104
|
+
self._suspending = False
|
|
105
|
+
self._subscription_meta: list[dict[str, Any]] = []
|
|
106
|
+
|
|
107
|
+
self.io_pool: ThreadPoolExecutor = get_executor()
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def is_connected(self) -> bool:
|
|
111
|
+
"""Check connection status."""
|
|
112
|
+
return self.nc is not None and self.nc.is_connected
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def is_closed(self) -> bool:
|
|
116
|
+
"""Check if the client is closed."""
|
|
117
|
+
return self._closed
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def max_payload_size(self) -> int:
|
|
121
|
+
"""Get the maximum payload size."""
|
|
122
|
+
return self._max_payload_size
|
|
123
|
+
|
|
124
|
+
def create_isolated_client(self, options: RPCClientOptions) -> "RPCClient":
|
|
125
|
+
"""Create a new isolated RPC client."""
|
|
126
|
+
return RPCClient(options)
|
|
127
|
+
|
|
128
|
+
async def connect(self) -> NATSClient:
|
|
129
|
+
"""Connect to NATS server."""
|
|
130
|
+
if self.nc and self.nc.is_connected:
|
|
131
|
+
return self.nc
|
|
132
|
+
|
|
133
|
+
if not self._connection_task:
|
|
134
|
+
self._connection_task = asyncio.create_task(self._connect())
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
self.nc = await self._connection_task
|
|
138
|
+
finally:
|
|
139
|
+
self._connection_task = None
|
|
140
|
+
|
|
141
|
+
return self.nc
|
|
142
|
+
|
|
143
|
+
async def _connect(self) -> NATSClient:
|
|
144
|
+
"""Internal connection method."""
|
|
145
|
+
# Build connection options
|
|
146
|
+
connect_opts: ConnectionOptions = {
|
|
147
|
+
"servers": self.options["servers"],
|
|
148
|
+
"name": self.options["name"],
|
|
149
|
+
"allow_reconnect": self.options.get("reconnect", True),
|
|
150
|
+
"max_reconnect_attempts": self.options.get("max_reconnect_attempts", -1),
|
|
151
|
+
"reconnect_time_wait": int(
|
|
152
|
+
self.options.get("reconnect_time_wait", 2000) / 1000
|
|
153
|
+
), # Convert to seconds
|
|
154
|
+
# "no_echo": True, # Don't echo messages back to the client
|
|
155
|
+
"pending_size": 6 * 1024 * 1024, # 6MB pending buffer
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
# Add auth if provided
|
|
159
|
+
if auth := self.options.get("auth"):
|
|
160
|
+
connect_opts["user"] = auth.get("user")
|
|
161
|
+
connect_opts["password"] = auth.get("password")
|
|
162
|
+
|
|
163
|
+
# Add TLS if provided
|
|
164
|
+
if tls := self.options.get("tls"):
|
|
165
|
+
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
|
|
166
|
+
if tls.get("ca"):
|
|
167
|
+
context.load_verify_locations(tls["ca"])
|
|
168
|
+
if tls.get("cert") and tls.get("key"):
|
|
169
|
+
context.load_cert_chain(tls["cert"], tls["key"])
|
|
170
|
+
connect_opts["tls"] = context
|
|
171
|
+
|
|
172
|
+
self.nc = await connect(**connect_opts)
|
|
173
|
+
|
|
174
|
+
# Initialize service
|
|
175
|
+
self.service.init(self.nc)
|
|
176
|
+
|
|
177
|
+
# Get max_payload from server info
|
|
178
|
+
self._max_payload_size = self.nc.max_payload
|
|
179
|
+
|
|
180
|
+
# Reserve 8KB for NATS protocol overhead and MsgPack envelope per message
|
|
181
|
+
self._max_payload_size = self._max_payload_size - 8192
|
|
182
|
+
|
|
183
|
+
# Restore subscriptions after reconnect (used by suspend/connect cycle)
|
|
184
|
+
if self._subscription_meta:
|
|
185
|
+
metas = list(self._subscription_meta)
|
|
186
|
+
self._subscription_meta.clear()
|
|
187
|
+
for meta in metas:
|
|
188
|
+
await self.subscribe(meta["pattern"], meta["handler"], **(meta.get("options") or {}))
|
|
189
|
+
|
|
190
|
+
return self.nc
|
|
191
|
+
|
|
192
|
+
async def disconnect(self) -> None:
|
|
193
|
+
"""Disconnect from NATS server."""
|
|
194
|
+
self._closed = True
|
|
195
|
+
self._subscription_meta.clear()
|
|
196
|
+
|
|
197
|
+
# Cleanup pending requests
|
|
198
|
+
for pending in self.pending_requests.values():
|
|
199
|
+
if timeout_handle := pending.get("timeout"):
|
|
200
|
+
timeout_handle.cancel()
|
|
201
|
+
if reject := pending.get("reject"):
|
|
202
|
+
reject(create_error(ErrorCode.CONNECTION_CLOSED, "Connection closed"))
|
|
203
|
+
self.pending_requests.clear()
|
|
204
|
+
|
|
205
|
+
# Cleanup stream handlers
|
|
206
|
+
for handler in self.stream_handlers.values():
|
|
207
|
+
try:
|
|
208
|
+
if end := handler.get("end"):
|
|
209
|
+
end()
|
|
210
|
+
except Exception:
|
|
211
|
+
pass
|
|
212
|
+
self.stream_handlers.clear()
|
|
213
|
+
|
|
214
|
+
# Cleanup pull iterators
|
|
215
|
+
await asyncio.gather(
|
|
216
|
+
*[cleanup() for cleanup in self.pull_iterator_cleanups.values()], return_exceptions=True
|
|
217
|
+
)
|
|
218
|
+
self.pull_iterator_cleanups.clear()
|
|
219
|
+
|
|
220
|
+
# Cleanup callbacks
|
|
221
|
+
await asyncio.gather(
|
|
222
|
+
*[cleanup() for cleanup in self.callback_cleanups.values()], return_exceptions=True
|
|
223
|
+
)
|
|
224
|
+
self.callback_cleanups.clear()
|
|
225
|
+
|
|
226
|
+
# Unsubscribe all subscriptions
|
|
227
|
+
for subs in self.subscriptions.values():
|
|
228
|
+
for sub in subs:
|
|
229
|
+
with contextlib.suppress(Exception):
|
|
230
|
+
await sub.unsubscribe()
|
|
231
|
+
self.subscriptions.clear()
|
|
232
|
+
|
|
233
|
+
# Clear chunking manager
|
|
234
|
+
self.chunking_manager = ChunkingManager()
|
|
235
|
+
|
|
236
|
+
# Shutdown thread pool
|
|
237
|
+
# self.io_pool.shutdown(wait=False)
|
|
238
|
+
|
|
239
|
+
# Disconnect all isolated clients, continue even if some fail
|
|
240
|
+
if self.isolated_clients:
|
|
241
|
+
await asyncio.gather(
|
|
242
|
+
*[client.disconnect() for client in self.isolated_clients],
|
|
243
|
+
return_exceptions=True,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Close connection with timeout
|
|
247
|
+
if self.nc:
|
|
248
|
+
timeout = self.options.get("disconnect_timeout", 2000) / 1000
|
|
249
|
+
with contextlib.suppress(TimeoutError, Exception):
|
|
250
|
+
await asyncio.wait_for(self.nc.close(), timeout=timeout)
|
|
251
|
+
self.nc = None
|
|
252
|
+
|
|
253
|
+
async def suspend(self) -> None:
|
|
254
|
+
"""Suspend the connection without marking as closed, preserving subscription metadata for reconnect."""
|
|
255
|
+
# Block on_finish-driven unsubscribe from clearing _subscription_meta
|
|
256
|
+
# while we tear the transport down — the task ending here is not a user-
|
|
257
|
+
# initiated unsubscribe.
|
|
258
|
+
self._suspending = True
|
|
259
|
+
try:
|
|
260
|
+
await self._do_suspend()
|
|
261
|
+
finally:
|
|
262
|
+
self._suspending = False
|
|
263
|
+
|
|
264
|
+
async def _do_suspend(self) -> None:
|
|
265
|
+
# Cleanup pending requests
|
|
266
|
+
for pending in self.pending_requests.values():
|
|
267
|
+
if timeout_handle := pending.get("timeout"):
|
|
268
|
+
timeout_handle.cancel()
|
|
269
|
+
if reject := pending.get("reject"):
|
|
270
|
+
reject(create_error(ErrorCode.CONNECTION_CLOSED, "Connection closed"))
|
|
271
|
+
self.pending_requests.clear()
|
|
272
|
+
|
|
273
|
+
# Cleanup stream handlers
|
|
274
|
+
for handler in self.stream_handlers.values():
|
|
275
|
+
try:
|
|
276
|
+
if end := handler.get("end"):
|
|
277
|
+
end()
|
|
278
|
+
except Exception:
|
|
279
|
+
pass
|
|
280
|
+
self.stream_handlers.clear()
|
|
281
|
+
|
|
282
|
+
# Cleanup pull iterators
|
|
283
|
+
await asyncio.gather(
|
|
284
|
+
*[cleanup() for cleanup in self.pull_iterator_cleanups.values()], return_exceptions=True
|
|
285
|
+
)
|
|
286
|
+
self.pull_iterator_cleanups.clear()
|
|
287
|
+
|
|
288
|
+
# Cleanup callbacks
|
|
289
|
+
await asyncio.gather(
|
|
290
|
+
*[cleanup() for cleanup in self.callback_cleanups.values()], return_exceptions=True
|
|
291
|
+
)
|
|
292
|
+
self.callback_cleanups.clear()
|
|
293
|
+
|
|
294
|
+
# Unsubscribe all subscriptions
|
|
295
|
+
for subs in self.subscriptions.values():
|
|
296
|
+
for sub in subs:
|
|
297
|
+
with contextlib.suppress(Exception):
|
|
298
|
+
await sub.unsubscribe()
|
|
299
|
+
self.subscriptions.clear()
|
|
300
|
+
|
|
301
|
+
# Clear chunking manager
|
|
302
|
+
self.chunking_manager = ChunkingManager()
|
|
303
|
+
|
|
304
|
+
# Disconnect all isolated clients, continue even if some fail
|
|
305
|
+
if self.isolated_clients:
|
|
306
|
+
await asyncio.gather(
|
|
307
|
+
*[client.disconnect() for client in self.isolated_clients],
|
|
308
|
+
return_exceptions=True,
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
# Close connection with timeout
|
|
312
|
+
if self.nc:
|
|
313
|
+
timeout = self.options.get("disconnect_timeout", 2000) / 1000
|
|
314
|
+
with contextlib.suppress(TimeoutError, Exception):
|
|
315
|
+
await asyncio.wait_for(self.nc.close(), timeout=timeout)
|
|
316
|
+
self.nc = None
|
|
317
|
+
|
|
318
|
+
def reconfigure(
|
|
319
|
+
self,
|
|
320
|
+
servers: list[str] | None = None,
|
|
321
|
+
auth: RPCAuthOptions | None = None,
|
|
322
|
+
) -> None:
|
|
323
|
+
"""Update connection options between suspend() and connect().
|
|
324
|
+
|
|
325
|
+
Used for token rotation / endpoint switching: subscription metadata is
|
|
326
|
+
preserved by suspend(), reconfigure() points the next connect() at the
|
|
327
|
+
new server, and connect() re-subscribes everything on the fresh
|
|
328
|
+
transport.
|
|
329
|
+
"""
|
|
330
|
+
if self.nc and self.nc.is_connected:
|
|
331
|
+
raise RuntimeError("Cannot reconfigure while connected. Call suspend() first.")
|
|
332
|
+
if servers is not None:
|
|
333
|
+
self.options["servers"] = servers
|
|
334
|
+
if auth is not None:
|
|
335
|
+
self.options["auth"] = auth
|
|
336
|
+
for child in self.isolated_clients:
|
|
337
|
+
child.reconfigure(servers=servers, auth=auth)
|
|
338
|
+
|
|
339
|
+
async def _with_no_responder_retry(
|
|
340
|
+
self,
|
|
341
|
+
fn: Callable[[], Awaitable[T]],
|
|
342
|
+
override: NoResponderRetryOptions | None = None,
|
|
343
|
+
) -> T:
|
|
344
|
+
"""Retry a call on NoRespondersError with configurable delays.
|
|
345
|
+
|
|
346
|
+
``override`` lets a single call extend (or shrink) the retry window
|
|
347
|
+
beyond the client-wide default — useful when a specific responder is
|
|
348
|
+
known to be flaky (e.g. a child process that may be restarting).
|
|
349
|
+
"""
|
|
350
|
+
src = override if override is not None else self.options.get("no_responder_retry", {}) or {}
|
|
351
|
+
max_retries = src.get("max_retries", 3)
|
|
352
|
+
delays = src.get("delays", [0.5, 1.0, 2.0])
|
|
353
|
+
|
|
354
|
+
for attempt in range(max_retries + 1):
|
|
355
|
+
try:
|
|
356
|
+
return await fn()
|
|
357
|
+
except Exception as e:
|
|
358
|
+
is_no_responder = (
|
|
359
|
+
isinstance(e, errors.NoRespondersError)
|
|
360
|
+
or ("no responders" in str(e).lower())
|
|
361
|
+
or (isinstance(e, RPCException) and e.code == "503")
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
if not is_no_responder or attempt >= max_retries or self._closed:
|
|
365
|
+
raise
|
|
366
|
+
|
|
367
|
+
delay = delays[min(attempt, len(delays) - 1)]
|
|
368
|
+
await asyncio.sleep(delay)
|
|
369
|
+
|
|
370
|
+
# Should never reach here, but satisfy type checker
|
|
371
|
+
raise RuntimeError("Retry loop exhausted")
|
|
372
|
+
|
|
373
|
+
async def publish(
|
|
374
|
+
self, subject: str, data: Any, headers: dict[str, str] | None = None, reply: str | None = None
|
|
375
|
+
) -> None:
|
|
376
|
+
"""Public publish method with automatic chunking."""
|
|
377
|
+
if not self.nc:
|
|
378
|
+
raise RuntimeError("Not connected")
|
|
379
|
+
|
|
380
|
+
encoded = encode(data)
|
|
381
|
+
|
|
382
|
+
replyTo = reply if reply else ""
|
|
383
|
+
|
|
384
|
+
# Small enough to send directly
|
|
385
|
+
if len(encoded) <= self._max_payload_size:
|
|
386
|
+
await self.nc.publish(subject, encoded, headers=headers, reply=replyTo)
|
|
387
|
+
return
|
|
388
|
+
|
|
389
|
+
# Message is too large, chunk it
|
|
390
|
+
transfer_id = generate_id()
|
|
391
|
+
total_chunks = (len(encoded) + self._max_payload_size - 1) // self._max_payload_size
|
|
392
|
+
|
|
393
|
+
# Send header message first
|
|
394
|
+
header_msg: ChunkedTransferHeader = {
|
|
395
|
+
"type": "chunked",
|
|
396
|
+
"transferId": transfer_id,
|
|
397
|
+
"totalChunks": total_chunks,
|
|
398
|
+
"totalSize": len(encoded),
|
|
399
|
+
"chunkSize": self._max_payload_size,
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
# Header message includes original headers if any
|
|
403
|
+
hdrs = headers or {}
|
|
404
|
+
hdrs["x-chunked-transfer"] = "header"
|
|
405
|
+
hdrs["x-chunk-id"] = transfer_id
|
|
406
|
+
|
|
407
|
+
await self.nc.publish(subject, encode(header_msg), headers=hdrs, reply=replyTo)
|
|
408
|
+
|
|
409
|
+
# Send chunks lazily from generator (one at a time, not materialized)
|
|
410
|
+
for i, chunk in enumerate(create_chunks(encoded, transfer_id, self._max_payload_size)):
|
|
411
|
+
chunk_hdrs = {"x-chunked-transfer": "chunk", "x-chunk-id": transfer_id, "x-chunk-index": str(i)}
|
|
412
|
+
|
|
413
|
+
# Send raw chunk data (not encoded)
|
|
414
|
+
await self.nc.publish(subject, chunk["data"], headers=chunk_hdrs, reply=replyTo)
|
|
415
|
+
|
|
416
|
+
# Yield every 50 chunks to prevent blocking
|
|
417
|
+
if i > 0 and i % 50 == 0:
|
|
418
|
+
await asyncio.sleep(0)
|
|
419
|
+
|
|
420
|
+
async def subscribe(
|
|
421
|
+
self,
|
|
422
|
+
pattern: str,
|
|
423
|
+
handler: Callable[[Any], None] | Callable[[Any], Coroutine[Any, Any, None]],
|
|
424
|
+
queue: str = "",
|
|
425
|
+
) -> Callable[[], Coroutine[Any, Any, None]]:
|
|
426
|
+
"""Public subscribe method with automatic chunk handling."""
|
|
427
|
+
if not self.nc:
|
|
428
|
+
raise RuntimeError("Not connected")
|
|
429
|
+
|
|
430
|
+
async def message_handler(msg: Msg) -> None:
|
|
431
|
+
try:
|
|
432
|
+
chunk_type = msg.headers.get("x-chunked-transfer") if msg.headers else None
|
|
433
|
+
|
|
434
|
+
if chunk_type == "header":
|
|
435
|
+
# Chunked transfer header
|
|
436
|
+
data = decode(msg.data)
|
|
437
|
+
chunk_id = msg.headers.get("x-chunk-id") if msg.headers else None
|
|
438
|
+
|
|
439
|
+
if not chunk_id or data.get("transferId") != chunk_id:
|
|
440
|
+
return
|
|
441
|
+
|
|
442
|
+
def on_complete(assembled_data: Any) -> None:
|
|
443
|
+
asyncio.create_task(self._handle_assembled_data(handler, assembled_data))
|
|
444
|
+
|
|
445
|
+
def on_error(error: Exception) -> None:
|
|
446
|
+
print(f"Error assembling chunks for {pattern}: {error}")
|
|
447
|
+
|
|
448
|
+
# Setup chunk assembly with pre-allocated buffer
|
|
449
|
+
self.chunking_manager.start_receiving(
|
|
450
|
+
data["transferId"],
|
|
451
|
+
data["totalChunks"],
|
|
452
|
+
on_complete,
|
|
453
|
+
on_error,
|
|
454
|
+
data.get("totalSize"), # Pass totalSize for pre-allocation
|
|
455
|
+
data.get("chunkSize"), # Pass chunkSize for correct offset calculation
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
elif chunk_type == "chunk":
|
|
459
|
+
# Chunk data
|
|
460
|
+
if not msg.headers:
|
|
461
|
+
return
|
|
462
|
+
|
|
463
|
+
chunk_id = msg.headers.get("x-chunk-id")
|
|
464
|
+
chunk_index = int(msg.headers.get("x-chunk-index", "0"))
|
|
465
|
+
|
|
466
|
+
if not chunk_id:
|
|
467
|
+
return
|
|
468
|
+
|
|
469
|
+
# Process raw chunk data
|
|
470
|
+
self.chunking_manager.process_chunk(
|
|
471
|
+
{"id": chunk_id, "chunkIndex": chunk_index, "data": msg.data, "isLast": False}
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
else:
|
|
475
|
+
# Regular message - decode MessagePack data
|
|
476
|
+
data = decode(msg.data)
|
|
477
|
+
if is_async_function(handler):
|
|
478
|
+
await handler(data) # type: ignore[misc]
|
|
479
|
+
else:
|
|
480
|
+
loop = asyncio.get_event_loop()
|
|
481
|
+
await loop.run_in_executor(self.io_pool, handler, data)
|
|
482
|
+
|
|
483
|
+
except Exception as e:
|
|
484
|
+
print(f"Error processing message for {pattern}:", e)
|
|
485
|
+
print(traceback.format_exc())
|
|
486
|
+
|
|
487
|
+
sub = await self.nc.subscribe(pattern, queue=queue, cb=message_handler)
|
|
488
|
+
|
|
489
|
+
# Ensure the subscription is ready
|
|
490
|
+
await asyncio.sleep(0)
|
|
491
|
+
|
|
492
|
+
if pattern not in self.subscriptions:
|
|
493
|
+
self.subscriptions[pattern] = []
|
|
494
|
+
self.subscriptions[pattern].append(sub)
|
|
495
|
+
|
|
496
|
+
# Store subscription metadata for suspend/reconnect
|
|
497
|
+
options: dict[str, Any] = {}
|
|
498
|
+
if queue:
|
|
499
|
+
options["queue"] = queue
|
|
500
|
+
meta = {"pattern": pattern, "handler": handler, "options": options}
|
|
501
|
+
self._subscription_meta.append(meta)
|
|
502
|
+
|
|
503
|
+
async def unsubscribe() -> None:
|
|
504
|
+
with contextlib.suppress(Exception):
|
|
505
|
+
await sub.unsubscribe()
|
|
506
|
+
|
|
507
|
+
if pattern in self.subscriptions:
|
|
508
|
+
self.subscriptions[pattern] = [s for s in self.subscriptions[pattern] if s != sub]
|
|
509
|
+
if not self.subscriptions[pattern]:
|
|
510
|
+
del self.subscriptions[pattern]
|
|
511
|
+
|
|
512
|
+
# During suspend the NATS msg-task ends as a side-effect of the
|
|
513
|
+
# transport teardown — we want to keep _subscription_meta so that
|
|
514
|
+
# the next connect() can restore subscriptions.
|
|
515
|
+
if not self._suspending:
|
|
516
|
+
self._subscription_meta = [m for m in self._subscription_meta if m["pattern"] != pattern]
|
|
517
|
+
|
|
518
|
+
async def on_finish(fut: asyncio.Task[None]) -> None:
|
|
519
|
+
with contextlib.suppress(Exception):
|
|
520
|
+
await asyncio.wait_for(fut, None)
|
|
521
|
+
await unsubscribe()
|
|
522
|
+
|
|
523
|
+
msg_task: asyncio.Task[None] | None = getattr(sub, "_wait_for_msgs_task", None)
|
|
524
|
+
if msg_task:
|
|
525
|
+
asyncio.create_task(on_finish(msg_task))
|
|
526
|
+
|
|
527
|
+
return unsubscribe
|
|
528
|
+
|
|
529
|
+
async def _handle_assembled_data(self, handler: Callable[[Any], Any], data: Any) -> None:
|
|
530
|
+
"""Handle assembled data from chunks."""
|
|
531
|
+
try:
|
|
532
|
+
if is_async_function(handler):
|
|
533
|
+
await handler(data) # pyright: ignore[reportGeneralTypeIssues]
|
|
534
|
+
else:
|
|
535
|
+
# Run sync handlers in thread pool to avoid blocking
|
|
536
|
+
loop = asyncio.get_event_loop()
|
|
537
|
+
await loop.run_in_executor(self.io_pool, handler, data)
|
|
538
|
+
except Exception as e:
|
|
539
|
+
print(f"Error in handler: {e}")
|
|
540
|
+
|
|
541
|
+
async def request(
|
|
542
|
+
self,
|
|
543
|
+
subject: str,
|
|
544
|
+
data: Any,
|
|
545
|
+
timeout: int | None = None,
|
|
546
|
+
headers: dict[str, str] | None = None,
|
|
547
|
+
no_responder_retry: NoResponderRetryOptions | None = None,
|
|
548
|
+
) -> Any:
|
|
549
|
+
"""Native NATS request/reply, with automatic retry on no-responder errors.
|
|
550
|
+
|
|
551
|
+
``no_responder_retry`` overrides the client-wide retry config for this
|
|
552
|
+
single call.
|
|
553
|
+
"""
|
|
554
|
+
return await self._with_no_responder_retry(
|
|
555
|
+
lambda: self._request_once(subject, data, timeout=timeout, headers=headers),
|
|
556
|
+
override=no_responder_retry,
|
|
557
|
+
)
|
|
558
|
+
|
|
559
|
+
async def _request_once(
|
|
560
|
+
self, subject: str, data: Any, timeout: int | None = None, headers: dict[str, str] | None = None
|
|
561
|
+
) -> Any:
|
|
562
|
+
"""Single attempt of a native NATS request/reply."""
|
|
563
|
+
if not self.nc:
|
|
564
|
+
raise RuntimeError("Not connected")
|
|
565
|
+
|
|
566
|
+
timeout_sec = (timeout or 5000) / 1000 # Convert to seconds
|
|
567
|
+
encoded = encode(data)
|
|
568
|
+
|
|
569
|
+
try:
|
|
570
|
+
msg = await self.nc.request(subject, encoded, timeout=timeout_sec, headers=headers)
|
|
571
|
+
|
|
572
|
+
# Check for NATS micro service error response
|
|
573
|
+
if msg.headers and msg.headers.get("Nats-Service-Error-Code"):
|
|
574
|
+
error_code = msg.headers.get("Nats-Service-Error-Code", "500")
|
|
575
|
+
error_msg = msg.headers.get("Nats-Service-Error", "Service error")
|
|
576
|
+
# Try to decode error data
|
|
577
|
+
error_data = None
|
|
578
|
+
if msg.data:
|
|
579
|
+
with contextlib.suppress(Exception):
|
|
580
|
+
error_data = decode(msg.data)
|
|
581
|
+
raise create_error(error_code, error_msg, error_data)
|
|
582
|
+
|
|
583
|
+
decoded = decode(msg.data)
|
|
584
|
+
|
|
585
|
+
# Check if response contains an error field (for request handlers)
|
|
586
|
+
if isinstance(decoded, dict) and "error" in decoded:
|
|
587
|
+
code = cast(str, decoded.get("code", ErrorCode.INTERNAL_ERROR.value))
|
|
588
|
+
message = cast(str, decoded.get("error", "Unknown error"))
|
|
589
|
+
raise create_error(code, message, cast(Any, decoded))
|
|
590
|
+
|
|
591
|
+
return cast(Any, decoded)
|
|
592
|
+
except TimeoutError as e:
|
|
593
|
+
raise create_error(ErrorCode.TIMEOUT, f"Request to {subject!r} timed out after {timeout or 5000}ms") from e
|
|
594
|
+
except Exception as e:
|
|
595
|
+
if "no responders" in str(e).lower():
|
|
596
|
+
raise create_error(ErrorCode.NOT_FOUND, "No responders available") from e
|
|
597
|
+
raise
|
|
598
|
+
|
|
599
|
+
async def call(
|
|
600
|
+
self,
|
|
601
|
+
subject: str,
|
|
602
|
+
*args: Any,
|
|
603
|
+
no_responder_retry: NoResponderRetryOptions | None = None,
|
|
604
|
+
) -> Any:
|
|
605
|
+
"""Make an RPC call with no-responder retry.
|
|
606
|
+
|
|
607
|
+
``no_responder_retry`` overrides the client-wide retry config for this
|
|
608
|
+
single call.
|
|
609
|
+
"""
|
|
610
|
+
return await self._with_no_responder_retry(
|
|
611
|
+
lambda: self._call_once(subject, *args),
|
|
612
|
+
override=no_responder_retry,
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
async def _call_once(self, subject: str, *args: Any) -> Any:
|
|
616
|
+
"""Make a single RPC call without retry."""
|
|
617
|
+
if not self.is_connected and not self.is_closed:
|
|
618
|
+
await self.connect()
|
|
619
|
+
|
|
620
|
+
if not self.nc:
|
|
621
|
+
raise RuntimeError("Not connected")
|
|
622
|
+
|
|
623
|
+
request_id = generate_id()
|
|
624
|
+
timeout = self.options.get("timeout", 30000)
|
|
625
|
+
# Use different reply patterns for RPC vs service calls
|
|
626
|
+
reply_subject = (
|
|
627
|
+
f"rpc.reply.{request_id}" if subject.startswith("rpc.") else f"{subject}.reply.{request_id}"
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
# Create future for the response
|
|
631
|
+
future: asyncio.Future[Any] = asyncio.Future()
|
|
632
|
+
|
|
633
|
+
# Setup timeout
|
|
634
|
+
def handle_timeout() -> None:
|
|
635
|
+
if request_id in self.pending_requests:
|
|
636
|
+
del self.pending_requests[request_id]
|
|
637
|
+
if not future.done():
|
|
638
|
+
future.set_exception(errors.TimeoutError(f"RPC call to {subject!r} timed out after {timeout}ms"))
|
|
639
|
+
|
|
640
|
+
timeout_handle = asyncio.get_event_loop().call_later(timeout / 1000, handle_timeout)
|
|
641
|
+
|
|
642
|
+
# Store pending request
|
|
643
|
+
self.pending_requests[request_id] = {"future": future, "timeout": timeout_handle}
|
|
644
|
+
|
|
645
|
+
# Handle no responders
|
|
646
|
+
sub: Subscription | None = None
|
|
647
|
+
unsubscribe: Callable[[], Coroutine[Any, Any, None]] | None = None
|
|
648
|
+
|
|
649
|
+
# Unsubscribe function to clean up
|
|
650
|
+
async def unsubscribe_all() -> None:
|
|
651
|
+
if request_id in self.pending_requests:
|
|
652
|
+
self.pending_requests[request_id]["timeout"].cancel()
|
|
653
|
+
del self.pending_requests[request_id]
|
|
654
|
+
if sub and not sub._closed: # pyright: ignore[reportPrivateUsage]
|
|
655
|
+
with contextlib.suppress(Exception):
|
|
656
|
+
await sub.unsubscribe()
|
|
657
|
+
if unsubscribe:
|
|
658
|
+
with contextlib.suppress(Exception):
|
|
659
|
+
await unsubscribe()
|
|
660
|
+
|
|
661
|
+
# Subscribe to reply
|
|
662
|
+
async def handle_rpc_response(data: Any) -> None:
|
|
663
|
+
response = data # assuming data is already parsed as RPCResponse
|
|
664
|
+
if response.get("id") == request_id:
|
|
665
|
+
pending = self.pending_requests.get(response["id"])
|
|
666
|
+
|
|
667
|
+
if pending:
|
|
668
|
+
del self.pending_requests[response["id"]]
|
|
669
|
+
pending["timeout"].cancel()
|
|
670
|
+
await unsubscribe_all()
|
|
671
|
+
|
|
672
|
+
if "error" in response:
|
|
673
|
+
pending["future"].set_exception(RPCException.from_dict(response["error"]))
|
|
674
|
+
else:
|
|
675
|
+
result = response.get("result")
|
|
676
|
+
# Attach __methods to result for proxy method discovery
|
|
677
|
+
if "__methods" in response and result is not None and isinstance(result, dict):
|
|
678
|
+
result["__methods"] = response["__methods"]
|
|
679
|
+
pending["future"].set_result(result)
|
|
680
|
+
|
|
681
|
+
async def request_callback(msg: Msg) -> None:
|
|
682
|
+
# Check for no responders status (empty message with 503 status)
|
|
683
|
+
if (
|
|
684
|
+
(msg.data is None or len(msg.data) == 0) # pyright: ignore[reportUnnecessaryComparison]
|
|
685
|
+
and msg.headers
|
|
686
|
+
and msg.headers.get(Header.STATUS) == NO_RESPONDERS_STATUS
|
|
687
|
+
):
|
|
688
|
+
if not future.done():
|
|
689
|
+
future.set_exception(errors.NoRespondersError(subject))
|
|
690
|
+
|
|
691
|
+
# Cleanup
|
|
692
|
+
await unsubscribe_all()
|
|
693
|
+
|
|
694
|
+
unsubscribe = await self.subscribe(reply_subject, handle_rpc_response)
|
|
695
|
+
|
|
696
|
+
inbox = self.nc.new_inbox()
|
|
697
|
+
sub = await self.nc.subscribe(inbox, cb=request_callback, max_msgs=1)
|
|
698
|
+
|
|
699
|
+
try:
|
|
700
|
+
# Send request
|
|
701
|
+
message: RPCMessage = {"id": request_id, "method": "call", "params": args}
|
|
702
|
+
await self.publish(subject, message, reply=inbox)
|
|
703
|
+
|
|
704
|
+
# Wait for response
|
|
705
|
+
return await future
|
|
706
|
+
except Exception:
|
|
707
|
+
# Cleanup on error
|
|
708
|
+
await unsubscribe_all()
|
|
709
|
+
raise
|
|
710
|
+
|
|
711
|
+
def _handle_timeout(self, request_id: str, subject: str, future: asyncio.Future[Any], timeout: int) -> None:
|
|
712
|
+
"""Handle request timeout."""
|
|
713
|
+
if request_id in self.pending_requests:
|
|
714
|
+
del self.pending_requests[request_id]
|
|
715
|
+
if not future.done():
|
|
716
|
+
future.set_exception(create_error(ErrorCode.TIMEOUT, f"RPC call to {subject!r} timed out after {timeout}ms"))
|
|
717
|
+
|
|
718
|
+
def _handle_rpc_response(self, data: Any) -> None:
|
|
719
|
+
"""Handle RPC response."""
|
|
720
|
+
response = data
|
|
721
|
+
pending = self.pending_requests.get(response["id"])
|
|
722
|
+
|
|
723
|
+
if pending:
|
|
724
|
+
del self.pending_requests[response["id"]]
|
|
725
|
+
if timeout_handle := pending.get("timeout"):
|
|
726
|
+
timeout_handle.cancel()
|
|
727
|
+
|
|
728
|
+
future = pending["future"]
|
|
729
|
+
if error := response.get("error"):
|
|
730
|
+
future.set_exception(RPCException.from_dict(error))
|
|
731
|
+
else:
|
|
732
|
+
future.set_result(response.get("result"))
|
|
733
|
+
|
|
734
|
+
async def call_stream(
|
|
735
|
+
self,
|
|
736
|
+
subject: str,
|
|
737
|
+
*args: Any,
|
|
738
|
+
no_responder_retry: NoResponderRetryOptions | None = None,
|
|
739
|
+
) -> AsyncGenerator[Any, None]:
|
|
740
|
+
"""Make a streaming RPC call, with automatic retry on no-responder errors.
|
|
741
|
+
|
|
742
|
+
``no_responder_retry`` overrides the client-wide retry config for this
|
|
743
|
+
single call.
|
|
744
|
+
"""
|
|
745
|
+
src = (
|
|
746
|
+
no_responder_retry
|
|
747
|
+
if no_responder_retry is not None
|
|
748
|
+
else self.options.get("no_responder_retry", {}) or {}
|
|
749
|
+
)
|
|
750
|
+
max_retries = src.get("max_retries", 3)
|
|
751
|
+
delays = src.get("delays", [0.5, 1.0, 2.0])
|
|
752
|
+
|
|
753
|
+
for attempt in range(max_retries + 1):
|
|
754
|
+
try:
|
|
755
|
+
async for value in self._call_stream_once(subject, *args):
|
|
756
|
+
yield value
|
|
757
|
+
return
|
|
758
|
+
except Exception as e:
|
|
759
|
+
is_no_responder = (
|
|
760
|
+
isinstance(e, errors.NoRespondersError)
|
|
761
|
+
or ("no responders" in str(e).lower())
|
|
762
|
+
or (isinstance(e, RPCException) and e.code == "503")
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
if not is_no_responder or attempt >= max_retries or self._closed:
|
|
766
|
+
raise
|
|
767
|
+
|
|
768
|
+
delay = delays[min(attempt, len(delays) - 1)]
|
|
769
|
+
await asyncio.sleep(delay)
|
|
770
|
+
|
|
771
|
+
async def _call_stream_once(self, subject: str, *args: Any) -> AsyncGenerator[Any, None]:
|
|
772
|
+
"""Single attempt of a streaming RPC call."""
|
|
773
|
+
if not self.is_connected and not self.is_closed:
|
|
774
|
+
await self.connect()
|
|
775
|
+
|
|
776
|
+
if not self.nc:
|
|
777
|
+
raise RuntimeError("Not connected")
|
|
778
|
+
|
|
779
|
+
request_id = generate_id()
|
|
780
|
+
stream_subject = f"stream.{subject}.{request_id}"
|
|
781
|
+
|
|
782
|
+
# Stream state
|
|
783
|
+
queue: asyncio.Queue[Any] = asyncio.Queue()
|
|
784
|
+
ended = False
|
|
785
|
+
error: Exception | None = None
|
|
786
|
+
|
|
787
|
+
# Initialize variables
|
|
788
|
+
sub: Subscription | None = None
|
|
789
|
+
unsubscribe: Callable[[], Coroutine[Any, Any, None]] | None = None
|
|
790
|
+
|
|
791
|
+
def on_push(value: Any) -> None:
|
|
792
|
+
nonlocal ended
|
|
793
|
+
if not ended:
|
|
794
|
+
queue.put_nowait(value)
|
|
795
|
+
|
|
796
|
+
def on_end() -> None:
|
|
797
|
+
nonlocal ended
|
|
798
|
+
ended = True
|
|
799
|
+
queue.put_nowait(None) # End marker
|
|
800
|
+
|
|
801
|
+
def on_error(err: Exception) -> None:
|
|
802
|
+
nonlocal error, ended
|
|
803
|
+
error = err
|
|
804
|
+
ended = True
|
|
805
|
+
queue.put_nowait(None) # End marker
|
|
806
|
+
|
|
807
|
+
# Setup handlers
|
|
808
|
+
handler: dict[str, Callable[..., None]] = {
|
|
809
|
+
"push": on_push,
|
|
810
|
+
"end": on_end,
|
|
811
|
+
"error": on_error,
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
self.stream_handlers[request_id] = handler
|
|
815
|
+
|
|
816
|
+
# Unsubscribe function to clean up
|
|
817
|
+
async def unsubscribe_all() -> None:
|
|
818
|
+
nonlocal ended
|
|
819
|
+
|
|
820
|
+
if request_id in self.stream_handlers:
|
|
821
|
+
del self.stream_handlers[request_id]
|
|
822
|
+
if sub and not sub._closed: # pyright: ignore[reportPrivateUsage]
|
|
823
|
+
with contextlib.suppress(Exception):
|
|
824
|
+
await sub.unsubscribe()
|
|
825
|
+
if unsubscribe:
|
|
826
|
+
with contextlib.suppress(Exception):
|
|
827
|
+
await unsubscribe()
|
|
828
|
+
|
|
829
|
+
# Notify server to stop
|
|
830
|
+
if not ended:
|
|
831
|
+
ended = True
|
|
832
|
+
with contextlib.suppress(Exception):
|
|
833
|
+
await self.publish(f"{stream_subject}.cancel", {"id": request_id})
|
|
834
|
+
|
|
835
|
+
# Subscribe to stream messages
|
|
836
|
+
async def handle_stream_message(msg: StreamMessage) -> None:
|
|
837
|
+
if msg.get("id") != request_id:
|
|
838
|
+
return
|
|
839
|
+
|
|
840
|
+
stream_handler = self.stream_handlers.get(msg["id"])
|
|
841
|
+
if not stream_handler:
|
|
842
|
+
return
|
|
843
|
+
|
|
844
|
+
msg_type = msg.get("type")
|
|
845
|
+
if msg_type == "data":
|
|
846
|
+
stream_handler["push"](msg.get("data"))
|
|
847
|
+
elif msg_type == "end":
|
|
848
|
+
stream_handler["end"]()
|
|
849
|
+
await unsubscribe_all()
|
|
850
|
+
elif msg_type == "error":
|
|
851
|
+
error_data = cast(RPCError, msg.get("error"))
|
|
852
|
+
stream_handler["error"](RPCException.from_dict(error_data))
|
|
853
|
+
await unsubscribe_all()
|
|
854
|
+
|
|
855
|
+
async def request_callback(msg: Msg) -> None:
|
|
856
|
+
# Check for no responders status (empty message with 503 status)
|
|
857
|
+
if (
|
|
858
|
+
(msg.data is None or len(msg.data) == 0) # pyright: ignore[reportUnnecessaryComparison]
|
|
859
|
+
and msg.headers
|
|
860
|
+
and msg.headers.get(Header.STATUS) == NO_RESPONDERS_STATUS
|
|
861
|
+
):
|
|
862
|
+
stream_handler = self.stream_handlers.get(request_id)
|
|
863
|
+
if stream_handler:
|
|
864
|
+
stream_handler["error"](errors.NoRespondersError(subject))
|
|
865
|
+
await unsubscribe_all()
|
|
866
|
+
|
|
867
|
+
unsubscribe = await self.subscribe(stream_subject, handle_stream_message)
|
|
868
|
+
|
|
869
|
+
inbox = self.nc.new_inbox()
|
|
870
|
+
sub = await self.nc.subscribe(inbox, cb=request_callback, max_msgs=1)
|
|
871
|
+
|
|
872
|
+
try:
|
|
873
|
+
# Send request
|
|
874
|
+
stream_params: dict[str, Any] = {
|
|
875
|
+
"__stream": True,
|
|
876
|
+
"__streamSubject": stream_subject,
|
|
877
|
+
"args": args,
|
|
878
|
+
}
|
|
879
|
+
message: RPCMessage = {"id": request_id, "method": "stream", "params": stream_params}
|
|
880
|
+
await self.publish(subject, message, reply=inbox)
|
|
881
|
+
|
|
882
|
+
# Generator implementation
|
|
883
|
+
while True:
|
|
884
|
+
if error:
|
|
885
|
+
await unsubscribe_all()
|
|
886
|
+
raise error
|
|
887
|
+
|
|
888
|
+
try:
|
|
889
|
+
# Wait for next value
|
|
890
|
+
value = await queue.get()
|
|
891
|
+
if value is None: # End marker
|
|
892
|
+
if error:
|
|
893
|
+
await unsubscribe_all()
|
|
894
|
+
raise error
|
|
895
|
+
await unsubscribe_all()
|
|
896
|
+
return
|
|
897
|
+
yield value
|
|
898
|
+
except Exception as e:
|
|
899
|
+
await unsubscribe_all()
|
|
900
|
+
raise e
|
|
901
|
+
|
|
902
|
+
except Exception:
|
|
903
|
+
await unsubscribe_all()
|
|
904
|
+
raise
|
|
905
|
+
|
|
906
|
+
async def call_pull_iterator(self, subject: str, *args: Any) -> AsyncGenerator[Any, None]:
|
|
907
|
+
"""Make a pull-based iterator RPC call."""
|
|
908
|
+
if not self.is_connected and not self.is_closed:
|
|
909
|
+
await self.connect()
|
|
910
|
+
|
|
911
|
+
if not self.nc:
|
|
912
|
+
raise RuntimeError("Not connected")
|
|
913
|
+
|
|
914
|
+
iterator_id = generate_id()
|
|
915
|
+
request_subject = f"_rpc.iterator.{iterator_id}.request"
|
|
916
|
+
response_subject = f"_rpc.iterator.{iterator_id}.response"
|
|
917
|
+
|
|
918
|
+
# Initialize the pull iterator using regular call method
|
|
919
|
+
# We pass a special __pullIterator marker as the first argument
|
|
920
|
+
init_response = await self.call(
|
|
921
|
+
subject, {"__pullIterator": True, "__iteratorId": iterator_id, "args": args}
|
|
922
|
+
)
|
|
923
|
+
|
|
924
|
+
# The response should contain the iterator ID (same as we sent)
|
|
925
|
+
if not init_response or init_response.get("iteratorId") != iterator_id:
|
|
926
|
+
raise RuntimeError("Failed to initialize pull iterator")
|
|
927
|
+
|
|
928
|
+
# Subscribe to responses
|
|
929
|
+
response_queue: asyncio.Queue[PullIteratorResponse] = asyncio.Queue()
|
|
930
|
+
ended = False
|
|
931
|
+
error: Exception | None = None
|
|
932
|
+
|
|
933
|
+
async def handle_response(msg: PullIteratorResponse) -> None:
|
|
934
|
+
nonlocal ended, error
|
|
935
|
+
|
|
936
|
+
if msg.get("type") == "error":
|
|
937
|
+
if error_data := msg.get("error"):
|
|
938
|
+
error = RPCException.from_dict(error_data)
|
|
939
|
+
ended = True
|
|
940
|
+
elif msg.get("type") == "done":
|
|
941
|
+
ended = True
|
|
942
|
+
|
|
943
|
+
await response_queue.put(msg)
|
|
944
|
+
|
|
945
|
+
unsubscribe = await self.subscribe(response_subject, handle_response)
|
|
946
|
+
|
|
947
|
+
async def cleanup() -> None:
|
|
948
|
+
if unsubscribe is not None:
|
|
949
|
+
await unsubscribe()
|
|
950
|
+
|
|
951
|
+
if sub and not sub._closed: # pyright: ignore[reportPrivateUsage]
|
|
952
|
+
with contextlib.suppress(Exception):
|
|
953
|
+
await sub.unsubscribe()
|
|
954
|
+
|
|
955
|
+
# Send cancel request
|
|
956
|
+
if not ended:
|
|
957
|
+
with contextlib.suppress(Exception):
|
|
958
|
+
cancel_request: PullIteratorRequest = {
|
|
959
|
+
"id": iterator_id,
|
|
960
|
+
"type": "cancel",
|
|
961
|
+
}
|
|
962
|
+
await self.publish(request_subject, cancel_request)
|
|
963
|
+
|
|
964
|
+
async def request_callback(msg2: Msg) -> None:
|
|
965
|
+
nonlocal ended, error
|
|
966
|
+
|
|
967
|
+
# Check for no responders status (empty message with 503 status)
|
|
968
|
+
if (
|
|
969
|
+
(msg2.data is None or len(msg2.data) == 0) # pyright: ignore[reportUnnecessaryComparison]
|
|
970
|
+
and msg2.headers
|
|
971
|
+
and msg2.headers.get(Header.STATUS) == NO_RESPONDERS_STATUS
|
|
972
|
+
):
|
|
973
|
+
ended = True
|
|
974
|
+
error = create_error("503", str(errors.NoRespondersError(subject)))
|
|
975
|
+
|
|
976
|
+
msg: PullIteratorResponse = {
|
|
977
|
+
"type": "error",
|
|
978
|
+
"id": iterator_id,
|
|
979
|
+
"error": error.to_dict(),
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
await response_queue.put(msg)
|
|
983
|
+
|
|
984
|
+
inbox = self.nc.new_inbox()
|
|
985
|
+
sub = await self.nc.subscribe(inbox, cb=request_callback, max_msgs=1)
|
|
986
|
+
|
|
987
|
+
try:
|
|
988
|
+
while True:
|
|
989
|
+
# Send next request
|
|
990
|
+
next_request: PullIteratorRequest = {
|
|
991
|
+
"id": iterator_id,
|
|
992
|
+
"type": "next",
|
|
993
|
+
}
|
|
994
|
+
await self.publish(request_subject, next_request, reply=inbox)
|
|
995
|
+
|
|
996
|
+
# Wait for response
|
|
997
|
+
response = await response_queue.get()
|
|
998
|
+
|
|
999
|
+
if response.get("type") == "error":
|
|
1000
|
+
if error_data := response.get("error"):
|
|
1001
|
+
raise RPCException.from_dict(error_data)
|
|
1002
|
+
elif response.get("type") == "done":
|
|
1003
|
+
break
|
|
1004
|
+
elif response.get("type") == "value":
|
|
1005
|
+
yield response.get("value")
|
|
1006
|
+
|
|
1007
|
+
finally:
|
|
1008
|
+
await cleanup()
|
|
1009
|
+
|
|
1010
|
+
async def call_pull_iterator_with_callback(
|
|
1011
|
+
self,
|
|
1012
|
+
subject: str,
|
|
1013
|
+
callbacks: dict[str, Callable[..., Any]],
|
|
1014
|
+
oneway_methods: list[str],
|
|
1015
|
+
*args: Any,
|
|
1016
|
+
) -> AsyncGenerator[None, None]:
|
|
1017
|
+
"""Make a pull-iterator-with-callbacks RPC call.
|
|
1018
|
+
|
|
1019
|
+
Combines client-driven pull iteration (1 RTT per batch) with a oneway
|
|
1020
|
+
callback channel (fire-and-forget server→client) for low-latency data
|
|
1021
|
+
delivery with coarse-grained backpressure.
|
|
1022
|
+
|
|
1023
|
+
The returned async generator yields ``None`` for each batch boundary
|
|
1024
|
+
the server produces. Meaningful data travels through ``callbacks``.
|
|
1025
|
+
See packages/rpc/PULL_CALLBACK_PROTOCOL.md.
|
|
1026
|
+
"""
|
|
1027
|
+
if not self.is_connected and not self.is_closed:
|
|
1028
|
+
await self.connect()
|
|
1029
|
+
|
|
1030
|
+
if not self.nc:
|
|
1031
|
+
raise RuntimeError("Not connected")
|
|
1032
|
+
|
|
1033
|
+
iterator_id = generate_id()
|
|
1034
|
+
request_subject = f"_rpc.iterator.{iterator_id}.request"
|
|
1035
|
+
response_subject = f"_rpc.iterator.{iterator_id}.response"
|
|
1036
|
+
callback_subject = f"_rpc.cb.{iterator_id}"
|
|
1037
|
+
|
|
1038
|
+
callback_methods = list(callbacks.keys())
|
|
1039
|
+
|
|
1040
|
+
# Track a task-chain of pending callback handlers. The iterator loop
|
|
1041
|
+
# awaits this chain before yielding, so a slow handler blocks the
|
|
1042
|
+
# next `next()` request — which stalls the server at its own yield.
|
|
1043
|
+
# This is what gives true end-to-end backpressure.
|
|
1044
|
+
callback_task: asyncio.Task[None] | None = None
|
|
1045
|
+
|
|
1046
|
+
# Subscribe to callback channel BEFORE init call.
|
|
1047
|
+
async def handle_cb_msg(msg: Any) -> None:
|
|
1048
|
+
nonlocal callback_task
|
|
1049
|
+
if not isinstance(msg, dict):
|
|
1050
|
+
return
|
|
1051
|
+
method = msg.get("method")
|
|
1052
|
+
fn = callbacks.get(method) if method else None
|
|
1053
|
+
if fn is None:
|
|
1054
|
+
return
|
|
1055
|
+
fn_args = msg.get("args") or []
|
|
1056
|
+
|
|
1057
|
+
prev = callback_task
|
|
1058
|
+
|
|
1059
|
+
async def run_chained() -> None:
|
|
1060
|
+
if prev is not None:
|
|
1061
|
+
with contextlib.suppress(Exception):
|
|
1062
|
+
await prev
|
|
1063
|
+
try:
|
|
1064
|
+
if is_async_function(fn):
|
|
1065
|
+
await fn(*fn_args)
|
|
1066
|
+
else:
|
|
1067
|
+
fn(*fn_args)
|
|
1068
|
+
except Exception as e:
|
|
1069
|
+
print(f"[rpc] Pull-callback handler '{method}' threw: {e}")
|
|
1070
|
+
|
|
1071
|
+
callback_task = asyncio.create_task(run_chained())
|
|
1072
|
+
|
|
1073
|
+
cb_unsub = await self.subscribe(callback_subject, handle_cb_msg)
|
|
1074
|
+
|
|
1075
|
+
# Init the pull-callback session via regular RPC call.
|
|
1076
|
+
init_params: PullCallbackParams = {
|
|
1077
|
+
"__pullCallback": True,
|
|
1078
|
+
"__iteratorId": iterator_id,
|
|
1079
|
+
"__callbackSubject": callback_subject,
|
|
1080
|
+
"__callbackMethods": callback_methods,
|
|
1081
|
+
"__onewayMethods": list(oneway_methods),
|
|
1082
|
+
"args": list(args),
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
try:
|
|
1086
|
+
init_response = await self.call(subject, init_params)
|
|
1087
|
+
except Exception:
|
|
1088
|
+
await cb_unsub()
|
|
1089
|
+
raise
|
|
1090
|
+
|
|
1091
|
+
if not init_response or init_response.get("iteratorId") != iterator_id:
|
|
1092
|
+
await cb_unsub()
|
|
1093
|
+
raise RuntimeError("Failed to initialize pull-callback iterator")
|
|
1094
|
+
|
|
1095
|
+
response_queue: asyncio.Queue[PullIteratorResponse] = asyncio.Queue()
|
|
1096
|
+
ended = False
|
|
1097
|
+
error: Exception | None = None
|
|
1098
|
+
|
|
1099
|
+
async def handle_response(msg: PullIteratorResponse) -> None:
|
|
1100
|
+
nonlocal ended, error
|
|
1101
|
+
if msg.get("type") == "error":
|
|
1102
|
+
if error_data := msg.get("error"):
|
|
1103
|
+
error = RPCException.from_dict(error_data)
|
|
1104
|
+
ended = True
|
|
1105
|
+
elif msg.get("type") == "done":
|
|
1106
|
+
ended = True
|
|
1107
|
+
await response_queue.put(msg)
|
|
1108
|
+
|
|
1109
|
+
resp_unsub = await self.subscribe(response_subject, handle_response)
|
|
1110
|
+
|
|
1111
|
+
async def request_callback(msg2: Msg) -> None:
|
|
1112
|
+
nonlocal ended, error
|
|
1113
|
+
if (
|
|
1114
|
+
(msg2.data is None or len(msg2.data) == 0) # pyright: ignore[reportUnnecessaryComparison]
|
|
1115
|
+
and msg2.headers
|
|
1116
|
+
and msg2.headers.get(Header.STATUS) == NO_RESPONDERS_STATUS
|
|
1117
|
+
):
|
|
1118
|
+
ended = True
|
|
1119
|
+
error = create_error("503", str(errors.NoRespondersError(subject)))
|
|
1120
|
+
msg: PullIteratorResponse = {
|
|
1121
|
+
"type": "error",
|
|
1122
|
+
"id": iterator_id,
|
|
1123
|
+
"error": error.to_dict(),
|
|
1124
|
+
}
|
|
1125
|
+
await response_queue.put(msg)
|
|
1126
|
+
|
|
1127
|
+
inbox = self.nc.new_inbox()
|
|
1128
|
+
sub = await self.nc.subscribe(inbox, cb=request_callback, max_msgs=1)
|
|
1129
|
+
|
|
1130
|
+
async def cleanup() -> None:
|
|
1131
|
+
await cb_unsub()
|
|
1132
|
+
if resp_unsub is not None:
|
|
1133
|
+
await resp_unsub()
|
|
1134
|
+
if sub and not sub._closed: # pyright: ignore[reportPrivateUsage]
|
|
1135
|
+
with contextlib.suppress(Exception):
|
|
1136
|
+
await sub.unsubscribe()
|
|
1137
|
+
if not ended:
|
|
1138
|
+
with contextlib.suppress(Exception):
|
|
1139
|
+
cancel_request: PullIteratorRequest = {
|
|
1140
|
+
"id": iterator_id,
|
|
1141
|
+
"type": "cancel",
|
|
1142
|
+
}
|
|
1143
|
+
await self.publish(request_subject, cancel_request)
|
|
1144
|
+
|
|
1145
|
+
try:
|
|
1146
|
+
while True:
|
|
1147
|
+
next_request: PullIteratorRequest = {
|
|
1148
|
+
"id": iterator_id,
|
|
1149
|
+
"type": "next",
|
|
1150
|
+
}
|
|
1151
|
+
await self.publish(request_subject, next_request, reply=inbox)
|
|
1152
|
+
|
|
1153
|
+
response = await response_queue.get()
|
|
1154
|
+
|
|
1155
|
+
if response.get("type") == "error":
|
|
1156
|
+
if error_data := response.get("error"):
|
|
1157
|
+
raise RPCException.from_dict(error_data)
|
|
1158
|
+
elif response.get("type") == "done":
|
|
1159
|
+
break
|
|
1160
|
+
elif response.get("type") == "value":
|
|
1161
|
+
# Wait for all callback handlers dispatched so far. If a
|
|
1162
|
+
# handler awaits a bounded queue (backpressure), this
|
|
1163
|
+
# stalls the iterator here until the handler releases,
|
|
1164
|
+
# which suspends the server at its own yield.
|
|
1165
|
+
if callback_task is not None:
|
|
1166
|
+
with contextlib.suppress(Exception):
|
|
1167
|
+
await callback_task
|
|
1168
|
+
yield None
|
|
1169
|
+
finally:
|
|
1170
|
+
await cleanup()
|
|
1171
|
+
|
|
1172
|
+
def _handle_stream_message(self, msg: StreamMessage) -> None:
|
|
1173
|
+
"""Handle streaming message."""
|
|
1174
|
+
stream_handler = self.stream_handlers.get(msg["id"])
|
|
1175
|
+
if not stream_handler:
|
|
1176
|
+
return
|
|
1177
|
+
|
|
1178
|
+
if msg["type"] == "data":
|
|
1179
|
+
stream_handler["push"](msg.get("data"))
|
|
1180
|
+
elif msg["type"] == "end":
|
|
1181
|
+
stream_handler["push"](None) # End marker
|
|
1182
|
+
stream_handler["end"]()
|
|
1183
|
+
if msg["id"] in self.stream_handlers:
|
|
1184
|
+
del self.stream_handlers[msg["id"]]
|
|
1185
|
+
elif msg["type"] == "error":
|
|
1186
|
+
if error_data := msg.get("error"):
|
|
1187
|
+
stream_handler["error"](RPCException.from_dict(error_data))
|
|
1188
|
+
stream_handler["push"](None) # End marker
|
|
1189
|
+
if msg["id"] in self.stream_handlers:
|
|
1190
|
+
del self.stream_handlers[msg["id"]]
|
|
1191
|
+
|
|
1192
|
+
async def call_with_callback(
|
|
1193
|
+
self, subject: str, args: list[Any], callback: Callable[[Any], Any]
|
|
1194
|
+
) -> Callable[[], Coroutine[Any, Any, None]]:
|
|
1195
|
+
"""Make an RPC call with a callback subscription. Returns async unsubscribe."""
|
|
1196
|
+
if not self.is_connected and not self.is_closed:
|
|
1197
|
+
await self.connect()
|
|
1198
|
+
if not self.nc:
|
|
1199
|
+
raise RuntimeError("Not connected")
|
|
1200
|
+
|
|
1201
|
+
request_id = generate_id()
|
|
1202
|
+
callback_subject = f"rpc.cb.{request_id}"
|
|
1203
|
+
|
|
1204
|
+
# Subscribe to callback messages
|
|
1205
|
+
async def handle_callback_msg(msg: Any) -> None:
|
|
1206
|
+
if isinstance(msg, dict):
|
|
1207
|
+
if msg.get("type") == "data":
|
|
1208
|
+
try:
|
|
1209
|
+
if is_async_function(callback):
|
|
1210
|
+
await callback(msg.get("data"))
|
|
1211
|
+
else:
|
|
1212
|
+
callback(msg.get("data"))
|
|
1213
|
+
except Exception as e:
|
|
1214
|
+
print(f"[rpc] Callback error: {e}")
|
|
1215
|
+
elif msg.get("type") == "error":
|
|
1216
|
+
print(f"[rpc] Callback error: {msg.get('error')}")
|
|
1217
|
+
|
|
1218
|
+
unsub = await self.subscribe(callback_subject, handle_callback_msg)
|
|
1219
|
+
|
|
1220
|
+
# Send RPC request with callback marker
|
|
1221
|
+
callback_params: CallbackParams = {
|
|
1222
|
+
"__callback": True,
|
|
1223
|
+
"__callbackSubject": callback_subject,
|
|
1224
|
+
"args": list(args),
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
try:
|
|
1228
|
+
await self.call(subject, callback_params)
|
|
1229
|
+
except Exception:
|
|
1230
|
+
await unsub()
|
|
1231
|
+
raise
|
|
1232
|
+
|
|
1233
|
+
# Return async unsubscribe function
|
|
1234
|
+
async def unsubscribe() -> None:
|
|
1235
|
+
with contextlib.suppress(Exception):
|
|
1236
|
+
await self.publish(f"{callback_subject}.cancel", {"id": request_id})
|
|
1237
|
+
await unsub()
|
|
1238
|
+
|
|
1239
|
+
return unsubscribe
|
|
1240
|
+
|
|
1241
|
+
async def register_handler(
|
|
1242
|
+
self,
|
|
1243
|
+
namespace: str,
|
|
1244
|
+
handlers: object,
|
|
1245
|
+
isolated_connection: bool = False,
|
|
1246
|
+
without_decorators: bool = False,
|
|
1247
|
+
queue: str = "",
|
|
1248
|
+
) -> Callable[[], Coroutine[Any, Any, None]]:
|
|
1249
|
+
"""Register RPC handlers."""
|
|
1250
|
+
if not self.nc:
|
|
1251
|
+
raise RuntimeError("Not connected")
|
|
1252
|
+
|
|
1253
|
+
# Use isolated connection if requested
|
|
1254
|
+
client: RPCClient = self
|
|
1255
|
+
if isolated_connection:
|
|
1256
|
+
# Create isolated connection for this handler namespace
|
|
1257
|
+
opts: RPCClientOptions = {
|
|
1258
|
+
**self.options,
|
|
1259
|
+
"name": f"{self.options['name']}-handler-{namespace}",
|
|
1260
|
+
}
|
|
1261
|
+
client = self.create_isolated_client(opts)
|
|
1262
|
+
# Connect the isolated client
|
|
1263
|
+
await client.connect()
|
|
1264
|
+
self.isolated_clients.append(client)
|
|
1265
|
+
|
|
1266
|
+
unsubscribers: list[Callable[[], Coroutine[Any, Any, None]]] = []
|
|
1267
|
+
pull_iterator_ids: list[str] = []
|
|
1268
|
+
|
|
1269
|
+
# Extract methods based on option
|
|
1270
|
+
handlers_map = (
|
|
1271
|
+
extract_nested_methods_without_decorators(handlers)
|
|
1272
|
+
if without_decorators
|
|
1273
|
+
else extract_nested_methods_with_decorators(handlers)
|
|
1274
|
+
)
|
|
1275
|
+
method_names = list(handlers_map.keys())
|
|
1276
|
+
|
|
1277
|
+
for method, handler in handlers_map.items():
|
|
1278
|
+
subject = f"rpc.{namespace}.{method}"
|
|
1279
|
+
|
|
1280
|
+
async def handle_message(
|
|
1281
|
+
msg: Any, handler: Any = handler, method_names: list[str] = method_names
|
|
1282
|
+
) -> None:
|
|
1283
|
+
message = msg
|
|
1284
|
+
response: RPCResponse = {"id": message["id"], "__methods": method_names}
|
|
1285
|
+
|
|
1286
|
+
try:
|
|
1287
|
+
# Handle stream request
|
|
1288
|
+
params = message.get("params")
|
|
1289
|
+
is_stream_request = bool(
|
|
1290
|
+
isinstance(params, dict)
|
|
1291
|
+
and params.get("__stream") is not None
|
|
1292
|
+
and params.get("__streamSubject") is not None
|
|
1293
|
+
)
|
|
1294
|
+
|
|
1295
|
+
# Check if it's a pull iterator request
|
|
1296
|
+
# Could be direct object or wrapped in array from call()
|
|
1297
|
+
is_pull_iterator = False
|
|
1298
|
+
pull_params: dict[str, Any] = {}
|
|
1299
|
+
|
|
1300
|
+
if params and isinstance(params, dict) and params.get("__pullIterator"):
|
|
1301
|
+
is_pull_iterator = True
|
|
1302
|
+
pull_params = cast(dict[str, Any], params)
|
|
1303
|
+
elif (
|
|
1304
|
+
isinstance(params, list)
|
|
1305
|
+
and len(params) > 0 # pyright: ignore[reportUnknownArgumentType]
|
|
1306
|
+
and isinstance(params[0], dict)
|
|
1307
|
+
and params[0].get("__pullIterator")
|
|
1308
|
+
):
|
|
1309
|
+
is_pull_iterator = True
|
|
1310
|
+
pull_params = cast(dict[str, Any], params[0])
|
|
1311
|
+
|
|
1312
|
+
# Check if it's a pull-callback request
|
|
1313
|
+
is_pull_callback = False
|
|
1314
|
+
pc_params: dict[str, Any] = {}
|
|
1315
|
+
|
|
1316
|
+
if params and isinstance(params, dict) and params.get("__pullCallback"):
|
|
1317
|
+
is_pull_callback = True
|
|
1318
|
+
pc_params = cast(dict[str, Any], params)
|
|
1319
|
+
elif (
|
|
1320
|
+
isinstance(params, list)
|
|
1321
|
+
and len(params) > 0 # pyright: ignore[reportUnknownArgumentType]
|
|
1322
|
+
and isinstance(params[0], dict)
|
|
1323
|
+
and params[0].get("__pullCallback")
|
|
1324
|
+
):
|
|
1325
|
+
is_pull_callback = True
|
|
1326
|
+
pc_params = cast(dict[str, Any], params[0])
|
|
1327
|
+
|
|
1328
|
+
if is_stream_request:
|
|
1329
|
+
_params = cast(dict[str, Any], params)
|
|
1330
|
+
stream_subject = cast(str, _params["__streamSubject"])
|
|
1331
|
+
args = cast(list[Any], _params.get("args", []))
|
|
1332
|
+
|
|
1333
|
+
# Don't await stream requests - they run in background and send data via streamSubject
|
|
1334
|
+
# Awaiting would block the subscription handler and prevent processing of new messages
|
|
1335
|
+
async def run_stream() -> None:
|
|
1336
|
+
try:
|
|
1337
|
+
await handle_stream_request(
|
|
1338
|
+
handler,
|
|
1339
|
+
args,
|
|
1340
|
+
stream_subject,
|
|
1341
|
+
message["id"],
|
|
1342
|
+
client,
|
|
1343
|
+
client.io_pool,
|
|
1344
|
+
)
|
|
1345
|
+
except Exception as e:
|
|
1346
|
+
print(f"Stream request error for {method}: {e}")
|
|
1347
|
+
|
|
1348
|
+
asyncio.create_task(run_stream())
|
|
1349
|
+
return # Don't send RPC response for stream requests
|
|
1350
|
+
elif is_pull_iterator:
|
|
1351
|
+
# Handle pull iterator request
|
|
1352
|
+
args = cast(list[Any], pull_params.get("args", []))
|
|
1353
|
+
iterator_id = cast(str, pull_params.get("__iteratorId", message["id"]))
|
|
1354
|
+
cleanup = await handle_pull_iterator_request(
|
|
1355
|
+
handler,
|
|
1356
|
+
args,
|
|
1357
|
+
iterator_id,
|
|
1358
|
+
client,
|
|
1359
|
+
client.io_pool,
|
|
1360
|
+
)
|
|
1361
|
+
|
|
1362
|
+
# Store cleanup function for later
|
|
1363
|
+
client.pull_iterator_cleanups[iterator_id] = cleanup
|
|
1364
|
+
pull_iterator_ids.append(iterator_id)
|
|
1365
|
+
response["result"] = {"iteratorId": iterator_id}
|
|
1366
|
+
|
|
1367
|
+
# Send response with iterator ID
|
|
1368
|
+
reply_subject = f"rpc.reply.{message['id']}"
|
|
1369
|
+
await client.publish(reply_subject, response)
|
|
1370
|
+
elif is_pull_callback:
|
|
1371
|
+
# Handle pull-iterator-with-callbacks request
|
|
1372
|
+
pc_args = cast(list[Any], pc_params.get("args", []))
|
|
1373
|
+
pc_iterator_id = cast(str, pc_params.get("__iteratorId", message["id"]))
|
|
1374
|
+
pc_callback_subject = cast(str, pc_params.get("__callbackSubject", ""))
|
|
1375
|
+
pc_oneway_methods = cast(list[str], pc_params.get("__onewayMethods", []))
|
|
1376
|
+
|
|
1377
|
+
pc_cleanup = await handle_pull_callback_request(
|
|
1378
|
+
handler,
|
|
1379
|
+
pc_args,
|
|
1380
|
+
pc_iterator_id,
|
|
1381
|
+
pc_callback_subject,
|
|
1382
|
+
pc_oneway_methods,
|
|
1383
|
+
client,
|
|
1384
|
+
client.io_pool,
|
|
1385
|
+
)
|
|
1386
|
+
|
|
1387
|
+
client.pull_iterator_cleanups[pc_iterator_id] = pc_cleanup
|
|
1388
|
+
pull_iterator_ids.append(pc_iterator_id)
|
|
1389
|
+
response["result"] = {"iteratorId": pc_iterator_id}
|
|
1390
|
+
|
|
1391
|
+
reply_subject = f"rpc.reply.{message['id']}"
|
|
1392
|
+
await client.publish(reply_subject, response)
|
|
1393
|
+
elif (
|
|
1394
|
+
isinstance(params, dict)
|
|
1395
|
+
and params.get("__callback") is not None
|
|
1396
|
+
and params.get("__callbackSubject") is not None
|
|
1397
|
+
) or (
|
|
1398
|
+
isinstance(params, list)
|
|
1399
|
+
and len(params) > 0 # pyright: ignore[reportUnknownArgumentType]
|
|
1400
|
+
and isinstance(params[0], dict)
|
|
1401
|
+
and params[0].get("__callback")
|
|
1402
|
+
):
|
|
1403
|
+
# Handle callback subscription request
|
|
1404
|
+
_cb_params = cast(
|
|
1405
|
+
dict[str, Any],
|
|
1406
|
+
params[0] if isinstance(params, list) and params[0].get("__callback") else params,
|
|
1407
|
+
)
|
|
1408
|
+
callback_subject = cast(str, _cb_params["__callbackSubject"])
|
|
1409
|
+
cb_args = cast(list[Any], _cb_params.get("args", []))
|
|
1410
|
+
|
|
1411
|
+
cb_cleanup = await handle_callback_request(
|
|
1412
|
+
handler,
|
|
1413
|
+
cb_args,
|
|
1414
|
+
callback_subject,
|
|
1415
|
+
message["id"],
|
|
1416
|
+
client,
|
|
1417
|
+
client.io_pool,
|
|
1418
|
+
)
|
|
1419
|
+
client.callback_cleanups[message["id"]] = cb_cleanup
|
|
1420
|
+
|
|
1421
|
+
response["result"] = {"ok": True}
|
|
1422
|
+
reply_subject = f"rpc.reply.{message['id']}"
|
|
1423
|
+
await client.publish(reply_subject, response)
|
|
1424
|
+
else:
|
|
1425
|
+
# Normal RPC call
|
|
1426
|
+
result = await handle_normal_rpc(
|
|
1427
|
+
handler,
|
|
1428
|
+
message.get("params", []),
|
|
1429
|
+
client.io_pool,
|
|
1430
|
+
)
|
|
1431
|
+
response["result"] = result
|
|
1432
|
+
|
|
1433
|
+
# Send response
|
|
1434
|
+
reply_subject = f"rpc.reply.{message['id']}"
|
|
1435
|
+
await client.publish(reply_subject, response)
|
|
1436
|
+
|
|
1437
|
+
except Exception as e:
|
|
1438
|
+
response["error"] = format_error_dict(e)
|
|
1439
|
+
|
|
1440
|
+
try:
|
|
1441
|
+
# If handler raised an exception, send error response
|
|
1442
|
+
reply_subject = f"rpc.reply.{message['id']}"
|
|
1443
|
+
await client.publish(reply_subject, response)
|
|
1444
|
+
except Exception as publish_error:
|
|
1445
|
+
if client.is_closed:
|
|
1446
|
+
return # Ignore publish errors if client is closed
|
|
1447
|
+
|
|
1448
|
+
print(f"Failed to send error response: {publish_error}")
|
|
1449
|
+
|
|
1450
|
+
unsubscribe = await client.subscribe(subject, handle_message, queue=queue)
|
|
1451
|
+
unsubscribers.append(unsubscribe)
|
|
1452
|
+
|
|
1453
|
+
# Return combined unsubscribe function
|
|
1454
|
+
async def cleanup() -> None:
|
|
1455
|
+
# Unsubscribe all handlers
|
|
1456
|
+
await asyncio.gather(*(unsub() for unsub in unsubscribers), return_exceptions=True)
|
|
1457
|
+
|
|
1458
|
+
async def cleanup_iterator(iterator_id: str) -> None:
|
|
1459
|
+
if cleanup := client.pull_iterator_cleanups.get(iterator_id):
|
|
1460
|
+
await cleanup()
|
|
1461
|
+
del client.pull_iterator_cleanups[iterator_id]
|
|
1462
|
+
|
|
1463
|
+
# Cleanup pull iterators
|
|
1464
|
+
await asyncio.gather(
|
|
1465
|
+
*(cleanup_iterator(iterator_id) for iterator_id in pull_iterator_ids),
|
|
1466
|
+
return_exceptions=True,
|
|
1467
|
+
)
|
|
1468
|
+
|
|
1469
|
+
# Cleanup callbacks
|
|
1470
|
+
callback_cleanups = list(client.callback_cleanups.items())
|
|
1471
|
+
for cb_id, cb_cleanup in callback_cleanups:
|
|
1472
|
+
with contextlib.suppress(Exception):
|
|
1473
|
+
await cb_cleanup()
|
|
1474
|
+
client.callback_cleanups.pop(cb_id, None)
|
|
1475
|
+
|
|
1476
|
+
if isolated_connection:
|
|
1477
|
+
# Disconnect isolated client if it was created
|
|
1478
|
+
await client.disconnect()
|
|
1479
|
+
if client in self.isolated_clients:
|
|
1480
|
+
self.isolated_clients.remove(client)
|
|
1481
|
+
|
|
1482
|
+
return cleanup
|
|
1483
|
+
|
|
1484
|
+
async def on_request(
|
|
1485
|
+
self, pattern: str, handler: Callable[[Any], Any]
|
|
1486
|
+
) -> Callable[[], Coroutine[Any, None, None]]:
|
|
1487
|
+
"""Setup a request handler (responder)."""
|
|
1488
|
+
if not self.nc:
|
|
1489
|
+
raise RuntimeError("Not connected")
|
|
1490
|
+
|
|
1491
|
+
async def handle_request(msg: Msg) -> None:
|
|
1492
|
+
try:
|
|
1493
|
+
# Decode request
|
|
1494
|
+
data = decode(msg.data)
|
|
1495
|
+
|
|
1496
|
+
# Call handler with subject
|
|
1497
|
+
if is_async_function(handler):
|
|
1498
|
+
result = await handler(data) # pyright: ignore[reportGeneralTypeIssues]
|
|
1499
|
+
else:
|
|
1500
|
+
loop = asyncio.get_event_loop()
|
|
1501
|
+
func = partial(handler, data)
|
|
1502
|
+
result = await loop.run_in_executor(self.io_pool, func)
|
|
1503
|
+
|
|
1504
|
+
# Send response
|
|
1505
|
+
if msg.reply:
|
|
1506
|
+
response = encode(result)
|
|
1507
|
+
await msg.respond(response)
|
|
1508
|
+
|
|
1509
|
+
except Exception as e:
|
|
1510
|
+
# Send error response
|
|
1511
|
+
if msg.reply:
|
|
1512
|
+
error_response = encode(
|
|
1513
|
+
{
|
|
1514
|
+
"error": str(e),
|
|
1515
|
+
"code": e.code if isinstance(e, RPCException) else ErrorCode.INTERNAL_ERROR.value,
|
|
1516
|
+
}
|
|
1517
|
+
)
|
|
1518
|
+
await msg.respond(error_response)
|
|
1519
|
+
|
|
1520
|
+
sub = await self.nc.subscribe(pattern, cb=handle_request)
|
|
1521
|
+
|
|
1522
|
+
# Ensure the subscription is ready
|
|
1523
|
+
await asyncio.sleep(0)
|
|
1524
|
+
|
|
1525
|
+
async def unsubscribe() -> None:
|
|
1526
|
+
"""Unsubscribe from the request handler."""
|
|
1527
|
+
if sub:
|
|
1528
|
+
with contextlib.suppress(Exception):
|
|
1529
|
+
await sub.unsubscribe()
|
|
1530
|
+
|
|
1531
|
+
# Return unsubscribe function
|
|
1532
|
+
return unsubscribe
|
|
1533
|
+
|
|
1534
|
+
async def channel(self, channel_id: str, isolated_connection: bool = False) -> Channel:
|
|
1535
|
+
"""Create or join a bidirectional channel."""
|
|
1536
|
+
if isolated_connection:
|
|
1537
|
+
# Create a new isolated client for this channel
|
|
1538
|
+
client = self.create_isolated_client(
|
|
1539
|
+
{**self.options, "name": f"{self.options['name']}-channel-{channel_id}"}
|
|
1540
|
+
)
|
|
1541
|
+
self.isolated_clients.append(client)
|
|
1542
|
+
await client.connect()
|
|
1543
|
+
else:
|
|
1544
|
+
client = self
|
|
1545
|
+
|
|
1546
|
+
channel = Channel(cast(Any, client), channel_id)
|
|
1547
|
+
await channel.init()
|
|
1548
|
+
|
|
1549
|
+
# Store reference for cleanup if isolated
|
|
1550
|
+
if isolated_connection:
|
|
1551
|
+
setattr(channel, "_isolated_client", client) # noqa: B010
|
|
1552
|
+
|
|
1553
|
+
return channel
|
|
1554
|
+
|
|
1555
|
+
async def private_channel(
|
|
1556
|
+
self, channel_id: str, target_client_id: str, isolated_connection: bool = False
|
|
1557
|
+
) -> PrivateChannel:
|
|
1558
|
+
"""Create a private 1:1 channel."""
|
|
1559
|
+
if isolated_connection:
|
|
1560
|
+
# Create a new isolated client for this channel
|
|
1561
|
+
client = self.create_isolated_client(
|
|
1562
|
+
{**self.options, "name": f"{self.options['name']}-private-{channel_id}"}
|
|
1563
|
+
)
|
|
1564
|
+
self.isolated_clients.append(client)
|
|
1565
|
+
await client.connect()
|
|
1566
|
+
else:
|
|
1567
|
+
client = self
|
|
1568
|
+
|
|
1569
|
+
channel = PrivateChannel(cast(Any, client), channel_id, target_client_id)
|
|
1570
|
+
await channel.init()
|
|
1571
|
+
|
|
1572
|
+
# Store reference for cleanup if isolated
|
|
1573
|
+
if isolated_connection:
|
|
1574
|
+
setattr(channel, "_isolated_client", client) # noqa: B010
|
|
1575
|
+
|
|
1576
|
+
return channel
|
|
1577
|
+
|
|
1578
|
+
@overload
|
|
1579
|
+
def create_proxy(
|
|
1580
|
+
self, namespace: str, type_class: type[T], isolated_connection: Literal[False] | None = None
|
|
1581
|
+
) -> T: ...
|
|
1582
|
+
@overload
|
|
1583
|
+
def create_proxy(
|
|
1584
|
+
self, namespace: str, type_class: type[T], isolated_connection: Literal[True]
|
|
1585
|
+
) -> ProxyWithClose[T]: ...
|
|
1586
|
+
@overload
|
|
1587
|
+
def create_proxy(
|
|
1588
|
+
self, namespace: str, type_class: None = None, isolated_connection: Literal[False] | None = None
|
|
1589
|
+
) -> Any: ...
|
|
1590
|
+
@overload
|
|
1591
|
+
def create_proxy(
|
|
1592
|
+
self, namespace: str, type_class: None = None, isolated_connection: Literal[True] = True
|
|
1593
|
+
) -> ProxyWithClose[Any]: ...
|
|
1594
|
+
def create_proxy(
|
|
1595
|
+
self, namespace: str, type_class: type[T] | None = None, isolated_connection: bool | None = False
|
|
1596
|
+
) -> T | Any | ProxyWithClose[T] | ProxyWithClose[Any]:
|
|
1597
|
+
"""Create proxy for type-safe RPC calls."""
|
|
1598
|
+
if isolated_connection:
|
|
1599
|
+
# Create an isolated proxy with its own connection
|
|
1600
|
+
client = self.create_isolated_client(
|
|
1601
|
+
{**self.options, "name": f"{self.options['name']}-proxy-{namespace}"}
|
|
1602
|
+
)
|
|
1603
|
+
self.isolated_clients.append(client)
|
|
1604
|
+
|
|
1605
|
+
proxy = create_proxy(cast(Any, client), namespace)
|
|
1606
|
+
|
|
1607
|
+
# Store references for potential cleanup
|
|
1608
|
+
setattr(proxy, "_isolated_client", client) # noqa: B010
|
|
1609
|
+
setattr(proxy, "_parent_client", self) # noqa: B010
|
|
1610
|
+
return ProxyWithClose(proxy)
|
|
1611
|
+
else:
|
|
1612
|
+
return create_proxy(cast(Any, self), namespace)
|
|
1613
|
+
|
|
1614
|
+
@overload
|
|
1615
|
+
async def create_service_proxy(
|
|
1616
|
+
self,
|
|
1617
|
+
service_name: str,
|
|
1618
|
+
type_class: type[T],
|
|
1619
|
+
isolated_connection: Literal[False] | None = None,
|
|
1620
|
+
preferred_id: str | None = None,
|
|
1621
|
+
timeout: int | None = None,
|
|
1622
|
+
) -> T: ...
|
|
1623
|
+
@overload
|
|
1624
|
+
async def create_service_proxy(
|
|
1625
|
+
self,
|
|
1626
|
+
service_name: str,
|
|
1627
|
+
type_class: type[T],
|
|
1628
|
+
isolated_connection: Literal[True],
|
|
1629
|
+
preferred_id: str | None = None,
|
|
1630
|
+
timeout: int | None = None,
|
|
1631
|
+
) -> ProxyWithClose[T]: ...
|
|
1632
|
+
@overload
|
|
1633
|
+
async def create_service_proxy(
|
|
1634
|
+
self,
|
|
1635
|
+
service_name: str,
|
|
1636
|
+
type_class: None = None,
|
|
1637
|
+
isolated_connection: Literal[False] | None = None,
|
|
1638
|
+
preferred_id: str | None = None,
|
|
1639
|
+
timeout: int | None = None,
|
|
1640
|
+
) -> Any: ...
|
|
1641
|
+
@overload
|
|
1642
|
+
async def create_service_proxy(
|
|
1643
|
+
self,
|
|
1644
|
+
service_name: str,
|
|
1645
|
+
type_class: None = None,
|
|
1646
|
+
isolated_connection: Literal[True] = True,
|
|
1647
|
+
preferred_id: str | None = None,
|
|
1648
|
+
timeout: int | None = None,
|
|
1649
|
+
) -> ProxyWithClose[Any]: ...
|
|
1650
|
+
async def create_service_proxy(
|
|
1651
|
+
self,
|
|
1652
|
+
service_name: str,
|
|
1653
|
+
type_class: type[T] | None = None,
|
|
1654
|
+
isolated_connection: bool | None = False,
|
|
1655
|
+
preferred_id: str | None = None,
|
|
1656
|
+
timeout: int | None = None,
|
|
1657
|
+
) -> T | Any | ProxyWithClose[T] | ProxyWithClose[Any]:
|
|
1658
|
+
"""Create a service client proxy with automatic service discovery."""
|
|
1659
|
+
if isolated_connection:
|
|
1660
|
+
# Create a new isolated client for this service proxy
|
|
1661
|
+
client = self.create_isolated_client(
|
|
1662
|
+
{**self.options, "name": f"{self.options['name']}-service-{service_name}"}
|
|
1663
|
+
)
|
|
1664
|
+
self.isolated_clients.append(client)
|
|
1665
|
+
await client.connect()
|
|
1666
|
+
else:
|
|
1667
|
+
client = self
|
|
1668
|
+
|
|
1669
|
+
# Discover available services
|
|
1670
|
+
monitor = client.service.monitor()
|
|
1671
|
+
services = await monitor.info(service_name)
|
|
1672
|
+
|
|
1673
|
+
if not services:
|
|
1674
|
+
if isolated_connection:
|
|
1675
|
+
await client.disconnect()
|
|
1676
|
+
if client in self.isolated_clients:
|
|
1677
|
+
self.isolated_clients.remove(client)
|
|
1678
|
+
raise RuntimeError(f"No services found with name: {service_name}")
|
|
1679
|
+
|
|
1680
|
+
# Select service (prefer specific ID if provided)
|
|
1681
|
+
selected = (
|
|
1682
|
+
next((s for s in services if s.id == preferred_id), services[0]) if preferred_id else services[0]
|
|
1683
|
+
)
|
|
1684
|
+
|
|
1685
|
+
# Create the proxy
|
|
1686
|
+
proxy = create_service_proxy(cast(Any, client), selected, timeout)
|
|
1687
|
+
|
|
1688
|
+
# If isolated, store references for potential cleanup
|
|
1689
|
+
if isolated_connection:
|
|
1690
|
+
setattr(proxy, "_isolated_client", client) # noqa: B010
|
|
1691
|
+
setattr(proxy, "_parent_client", self) # noqa: B010
|
|
1692
|
+
return ProxyWithClose(proxy)
|
|
1693
|
+
else:
|
|
1694
|
+
return proxy
|