@oneuptime/common 11.6.0 → 11.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (427) hide show
  1. package/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.ts +41 -24
  2. package/Models/AnalyticsModels/Index.ts +4 -0
  3. package/Models/AnalyticsModels/KubernetesCostAllocation.ts +842 -0
  4. package/Models/AnalyticsModels/MetricBaselineHourly.ts +2 -0
  5. package/Models/AnalyticsModels/MetricItemAggMV1m.ts +5 -2
  6. package/Models/AnalyticsModels/MetricItemAggMV1mByContainer.ts +5 -2
  7. package/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.ts +5 -2
  8. package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +5 -2
  9. package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +5 -2
  10. package/Models/AnalyticsModels/NetworkFlow.ts +54 -0
  11. package/Models/AnalyticsModels/SloHistory.ts +240 -0
  12. package/Models/DatabaseModels/Index.ts +20 -0
  13. package/Models/DatabaseModels/NetworkDevice.ts +453 -6
  14. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +7 -6
  15. package/Models/DatabaseModels/NetworkEndpoint.ts +753 -0
  16. package/Models/DatabaseModels/NetworkSite.ts +1155 -0
  17. package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +517 -0
  18. package/Models/DatabaseModels/NetworkSiteLink.ts +611 -0
  19. package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +520 -0
  20. package/Models/DatabaseModels/NetworkSiteType.ts +499 -0
  21. package/Models/DatabaseModels/ServiceLevelObjective.ts +1106 -0
  22. package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +762 -0
  23. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +444 -0
  24. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +443 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.ts +359 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.ts +48 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.ts +65 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.ts +88 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.ts +391 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  31. package/Server/Services/AnalyticsDatabaseService.ts +38 -10
  32. package/Server/Services/Index.ts +24 -0
  33. package/Server/Services/KubernetesCostAllocationService.ts +14 -0
  34. package/Server/Services/MetricService.ts +21 -2
  35. package/Server/Services/MonitorService.ts +22 -0
  36. package/Server/Services/NetworkDeviceService.ts +438 -2
  37. package/Server/Services/NetworkEndpointService.ts +414 -0
  38. package/Server/Services/NetworkSiteAssignmentRuleService.ts +98 -0
  39. package/Server/Services/NetworkSiteLinkService.ts +10 -0
  40. package/Server/Services/NetworkSiteService.ts +1254 -0
  41. package/Server/Services/NetworkSiteStatusTimelineService.ts +10 -0
  42. package/Server/Services/NetworkSiteTypeService.ts +10 -0
  43. package/Server/Services/ProjectService.ts +122 -2
  44. package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +457 -0
  45. package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +10 -0
  46. package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +10 -0
  47. package/Server/Services/ServiceLevelObjectiveService.ts +677 -0
  48. package/Server/Services/SloHistoryService.ts +101 -0
  49. package/Server/Services/UserNotificationSettingService.ts +37 -0
  50. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +9 -0
  51. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +15 -0
  52. package/Server/Utils/AnalyticsDatabase/Statement.ts +39 -3
  53. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +128 -52
  54. package/Server/Utils/Memory.ts +9 -1
  55. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +190 -12
  56. package/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  57. package/Server/Utils/Monitor/DnsResolutionCache.ts +129 -0
  58. package/Server/Utils/Monitor/MonitorResource.ts +4 -30
  59. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +214 -39
  60. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +343 -0
  61. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +251 -0
  62. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +176 -142
  63. package/Server/Utils/Monitor/OuiLookupUtil.ts +49 -0
  64. package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +17 -13
  65. package/Server/Utils/WhatsAppTemplateUtil.ts +7 -3
  66. package/Tests/Models/AnalyticsModels/AnalyticsBaseModel.test.ts +122 -0
  67. package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +135 -0
  68. package/Tests/Models/NetworkSiteHierarchy.test.ts +134 -0
  69. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +239 -0
  70. package/Tests/Server/Services/KubernetesCostAllocationAggregate.test.ts +338 -0
  71. package/Tests/Server/Services/MetricServiceAggregate.test.ts +142 -0
  72. package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +484 -0
  73. package/Tests/Server/Services/NetworkEndpointServiceUpsert.test.ts +686 -0
  74. package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +185 -0
  75. package/Tests/Server/Services/NetworkSiteService.test.ts +1354 -0
  76. package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +1313 -0
  77. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +1988 -0
  78. package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +164 -3
  79. package/Tests/Server/Utils/AnalyticsDatabase/Statement.test.ts +22 -0
  80. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +503 -0
  81. package/Tests/Server/Utils/Encryption.test.ts +70 -0
  82. package/Tests/Server/Utils/FileAttachmentMarkdownUtil.test.ts +225 -0
  83. package/Tests/Server/Utils/JsonWebToken.test.ts +175 -0
  84. package/Tests/Server/Utils/LocalFile.test.ts +258 -0
  85. package/Tests/Server/Utils/Memory.test.ts +213 -0
  86. package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +30 -0
  87. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +385 -0
  88. package/Tests/Server/Utils/Monitor/DnsResolutionCache.test.ts +194 -0
  89. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +155 -0
  90. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +600 -0
  91. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +151 -124
  92. package/Tests/Server/Utils/Monitor/SnmpInterfaceRateUtil.test.ts +496 -0
  93. package/Tests/Server/Utils/MonitorCriteriaDataExtractor.test.ts +175 -0
  94. package/Tests/Server/Utils/MonitorCriteriaMessageFormatter.test.ts +282 -0
  95. package/Tests/Server/Utils/OuiLookupUtil.test.ts +59 -0
  96. package/Tests/Server/Utils/SeriesResourceLabels.test.ts +117 -0
  97. package/Tests/Server/Utils/StackTraceParser.test.ts +370 -0
  98. package/Tests/Server/Utils/Stream.test.ts +87 -0
  99. package/Tests/Server/Utils/ValidateGlobalProviderProjectTeams.test.ts +221 -0
  100. package/Tests/Server/Utils/WhatsAppTemplateUtil.test.ts +199 -0
  101. package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +33 -0
  102. package/Tests/Types/Email.test.ts +198 -0
  103. package/Tests/Types/HashCode.test.ts +41 -0
  104. package/Tests/Types/Kubernetes/KubernetesObjectParser.test.ts +177 -0
  105. package/Tests/Types/Log/LogQueryParser.test.ts +186 -0
  106. package/Tests/Types/Log/LogQueryToFilter.test.ts +111 -0
  107. package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +141 -1
  108. package/Tests/Types/Monitor/MonitorType.test.ts +59 -1
  109. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +97 -0
  110. package/Tests/Types/Monitor/SnmpEndpointDiscovery.test.ts +151 -0
  111. package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +110 -6
  112. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +129 -0
  113. package/Tests/Types/SerializableObjectDictionary.test.ts +166 -0
  114. package/Tests/Types/Time/RangeStartAndEndDateTime.test.ts +98 -0
  115. package/Tests/Types/WebsiteRequest.test.ts +230 -0
  116. package/Tests/UI/Components/EntityFilterRoundTrip.test.tsx +103 -0
  117. package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +612 -0
  118. package/Tests/UI/Components/ModelTable/FilterDataToQuery.test.ts +275 -0
  119. package/Tests/UI/Utils/LogExport.test.ts +159 -0
  120. package/Tests/UI/Utils/Navigation.test.ts +183 -0
  121. package/Tests/UI/Utils/TableFilterUrlState.test.ts +539 -0
  122. package/Tests/UI/Utils/TableViewUrlState.test.ts +272 -0
  123. package/Tests/Utils/Base64.test.ts +51 -0
  124. package/Tests/Utils/Boolean.test.ts +76 -0
  125. package/Tests/Utils/Crypto.test.ts +48 -0
  126. package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +259 -0
  127. package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +162 -0
  128. package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +197 -0
  129. package/Tests/Utils/Enum.test.ts +54 -0
  130. package/Tests/Utils/IpCanonicalUtil.test.ts +85 -0
  131. package/Tests/Utils/Metrics/MetricSeriesFingerprint.test.ts +160 -0
  132. package/Tests/Utils/Monitor/EndpointAttachmentUtil.test.ts +836 -0
  133. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +218 -0
  134. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +447 -0
  135. package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +440 -0
  136. package/Tests/Utils/NetworkSite/MaterializedPathUtil.test.ts +205 -0
  137. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +221 -0
  138. package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +283 -0
  139. package/Tests/Utils/ObjectUtil.test.ts +30 -0
  140. package/Tests/Utils/Slo/SloStatusColor.test.ts +89 -0
  141. package/Tests/Utils/Slo/SloUtil.test.ts +1980 -0
  142. package/Tests/Utils/Slo/SloWidgetFormat.test.ts +605 -0
  143. package/Tests/Utils/TechStack.test.ts +50 -0
  144. package/Tests/Utils/Traces/CriticalPath.test.ts +178 -0
  145. package/Tests/Utils/ValueFormatter.test.ts +305 -0
  146. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +10 -0
  147. package/Types/AnalyticsDatabase/TableColumn.ts +23 -0
  148. package/Types/BaseDatabase/EqualTo.ts +9 -1
  149. package/Types/BaseDatabase/EqualToOrNull.ts +9 -1
  150. package/Types/BaseDatabase/NotEqual.ts +9 -1
  151. package/Types/Dashboard/DashboardComponentType.ts +1 -0
  152. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
  153. package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +42 -0
  154. package/Types/Dashboard/DashboardTemplates.ts +214 -0
  155. package/Types/Email/EmailTemplateType.ts +2 -0
  156. package/Types/Kubernetes/KubernetesCostIngest.ts +79 -0
  157. package/Types/Monitor/CriteriaFilter.ts +9 -0
  158. package/Types/Monitor/MonitorStep.ts +5 -8
  159. package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +27 -5
  160. package/Types/Monitor/MonitorType.ts +15 -5
  161. package/Types/Monitor/SnmpMonitor/ArpEntry.ts +14 -0
  162. package/Types/Monitor/SnmpMonitor/FdbEntry.ts +18 -0
  163. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +10 -3
  164. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -5
  165. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +12 -0
  166. package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +231 -3
  167. package/Types/NetworkSite/DefaultNetworkSiteType.ts +20 -0
  168. package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
  169. package/Types/Permission.ts +449 -0
  170. package/Types/ServiceLevelObjective/SliType.ts +6 -0
  171. package/Types/ServiceLevelObjective/SloMultiMonitorMode.ts +6 -0
  172. package/Types/ServiceLevelObjective/SloStatus.ts +9 -0
  173. package/Types/ServiceLevelObjective/SloWindowType.ts +6 -0
  174. package/Types/Telemetry/ServiceType.ts +1 -0
  175. package/UI/Components/Filters/EntityFilter.tsx +16 -0
  176. package/UI/Components/Filters/FilterViewer.tsx +22 -5
  177. package/UI/Components/List/List.tsx +8 -0
  178. package/UI/Components/ModelTable/BaseModelTable.tsx +309 -106
  179. package/UI/Components/ModelTable/FilterDataToQuery.ts +172 -0
  180. package/UI/Components/Navbar/NavBar.tsx +16 -2
  181. package/UI/Components/Navbar/NavBarMenuModal.tsx +3 -3
  182. package/UI/Utils/Navigation.ts +10 -0
  183. package/UI/Utils/TableFilterUrlState.ts +204 -17
  184. package/UI/Utils/TableViewUrlState.ts +165 -0
  185. package/Utils/Dashboard/Components/DashboardSloComponent.ts +114 -0
  186. package/Utils/Dashboard/Components/Index.ts +7 -0
  187. package/Utils/IpCanonicalUtil.ts +134 -0
  188. package/Utils/Monitor/EndpointAttachmentUtil.ts +508 -0
  189. package/Utils/Monitor/NetworkTopologyUtil.ts +157 -5
  190. package/Utils/NetworkSite/CidrMatchUtil.ts +296 -0
  191. package/Utils/NetworkSite/MaterializedPathUtil.ts +115 -0
  192. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +97 -0
  193. package/Utils/NetworkSite/SiteUptimeUtil.ts +111 -0
  194. package/Utils/Slo/SloStatusColor.ts +54 -0
  195. package/Utils/Slo/SloUtil.ts +637 -0
  196. package/Utils/Slo/SloWidgetFormat.ts +383 -0
  197. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js +25 -20
  198. package/build/dist/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel.js.map +1 -1
  199. package/build/dist/Models/AnalyticsModels/Index.js +4 -0
  200. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  201. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +713 -0
  202. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -0
  203. package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js +2 -0
  204. package/build/dist/Models/AnalyticsModels/MetricBaselineHourly.js.map +1 -1
  205. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js +5 -2
  206. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1m.js.map +1 -1
  207. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js +5 -2
  208. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByContainer.js.map +1 -1
  209. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js +5 -2
  210. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByHostV2.js.map +1 -1
  211. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +5 -2
  212. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js.map +1 -1
  213. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +5 -2
  214. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js.map +1 -1
  215. package/build/dist/Models/AnalyticsModels/NetworkFlow.js +44 -0
  216. package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
  217. package/build/dist/Models/AnalyticsModels/SloHistory.js +215 -0
  218. package/build/dist/Models/AnalyticsModels/SloHistory.js.map +1 -0
  219. package/build/dist/Models/DatabaseModels/Index.js +20 -0
  220. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  221. package/build/dist/Models/DatabaseModels/NetworkDevice.js +458 -6
  222. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  223. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +0 -6
  224. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  225. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js +779 -0
  226. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js.map +1 -0
  227. package/build/dist/Models/DatabaseModels/NetworkSite.js +1180 -0
  228. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -0
  229. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +534 -0
  230. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -0
  231. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js +629 -0
  232. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js.map +1 -0
  233. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +538 -0
  234. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -0
  235. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +522 -0
  236. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -0
  237. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +1124 -0
  238. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -0
  239. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +769 -0
  240. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -0
  241. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +460 -0
  242. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -0
  243. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +459 -0
  244. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -0
  245. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js +130 -0
  246. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js.map +1 -0
  247. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js +31 -0
  248. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js.map +1 -0
  249. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js +36 -0
  250. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js.map +1 -0
  251. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js +49 -0
  252. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js.map +1 -0
  253. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js +140 -0
  254. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js.map +1 -0
  255. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  256. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  257. package/build/dist/Server/Services/AnalyticsDatabaseService.js +32 -7
  258. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  259. package/build/dist/Server/Services/Index.js +24 -0
  260. package/build/dist/Server/Services/Index.js.map +1 -1
  261. package/build/dist/Server/Services/KubernetesCostAllocationService.js +12 -0
  262. package/build/dist/Server/Services/KubernetesCostAllocationService.js.map +1 -0
  263. package/build/dist/Server/Services/MetricService.js +21 -3
  264. package/build/dist/Server/Services/MetricService.js.map +1 -1
  265. package/build/dist/Server/Services/MonitorService.js +19 -0
  266. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  267. package/build/dist/Server/Services/NetworkDeviceService.js +351 -1
  268. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  269. package/build/dist/Server/Services/NetworkEndpointService.js +319 -0
  270. package/build/dist/Server/Services/NetworkEndpointService.js.map +1 -0
  271. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +90 -0
  272. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -0
  273. package/build/dist/Server/Services/NetworkSiteLinkService.js +9 -0
  274. package/build/dist/Server/Services/NetworkSiteLinkService.js.map +1 -0
  275. package/build/dist/Server/Services/NetworkSiteService.js +1038 -0
  276. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -0
  277. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js +9 -0
  278. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js.map +1 -0
  279. package/build/dist/Server/Services/NetworkSiteTypeService.js +9 -0
  280. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -0
  281. package/build/dist/Server/Services/ProjectService.js +98 -2
  282. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  283. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +358 -0
  284. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -0
  285. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +9 -0
  286. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -0
  287. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +9 -0
  288. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -0
  289. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +582 -0
  290. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -0
  291. package/build/dist/Server/Services/SloHistoryService.js +77 -0
  292. package/build/dist/Server/Services/SloHistoryService.js.map +1 -0
  293. package/build/dist/Server/Services/UserNotificationSettingService.js +20 -0
  294. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  295. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +9 -0
  296. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  297. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +15 -0
  298. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  299. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +31 -0
  300. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  301. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +105 -52
  302. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  303. package/build/dist/Server/Utils/Memory.js +9 -1
  304. package/build/dist/Server/Utils/Memory.js.map +1 -1
  305. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +132 -10
  306. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  307. package/build/dist/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  308. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js +77 -0
  309. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js.map +1 -0
  310. package/build/dist/Server/Utils/Monitor/MonitorResource.js +21 -41
  311. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  312. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +152 -40
  313. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  314. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +262 -0
  315. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -0
  316. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +201 -0
  317. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -0
  318. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +152 -120
  319. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  320. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js +44 -0
  321. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js.map +1 -0
  322. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +10 -10
  323. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -1
  324. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +5 -0
  325. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
  326. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +10 -0
  327. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  328. package/build/dist/Types/AnalyticsDatabase/TableColumn.js +7 -0
  329. package/build/dist/Types/AnalyticsDatabase/TableColumn.js.map +1 -1
  330. package/build/dist/Types/BaseDatabase/EqualTo.js +9 -1
  331. package/build/dist/Types/BaseDatabase/EqualTo.js.map +1 -1
  332. package/build/dist/Types/BaseDatabase/EqualToOrNull.js +9 -1
  333. package/build/dist/Types/BaseDatabase/EqualToOrNull.js.map +1 -1
  334. package/build/dist/Types/BaseDatabase/NotEqual.js +9 -1
  335. package/build/dist/Types/BaseDatabase/NotEqual.js.map +1 -1
  336. package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
  337. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  338. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
  339. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  340. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js +23 -0
  341. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js.map +1 -0
  342. package/build/dist/Types/Dashboard/DashboardTemplates.js +205 -0
  343. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  344. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  345. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  346. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js +21 -0
  347. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -0
  348. package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
  349. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  350. package/build/dist/Types/Monitor/MonitorStep.js +5 -5
  351. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  352. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +8 -0
  353. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -1
  354. package/build/dist/Types/Monitor/MonitorType.js +15 -5
  355. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  356. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js +2 -0
  357. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js.map +1 -0
  358. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js +2 -0
  359. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js.map +1 -0
  360. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +9 -3
  361. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  362. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +217 -3
  363. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
  364. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js +21 -0
  365. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js.map +1 -0
  366. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
  367. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  368. package/build/dist/Types/Permission.js +409 -0
  369. package/build/dist/Types/Permission.js.map +1 -1
  370. package/build/dist/Types/ServiceLevelObjective/SliType.js +7 -0
  371. package/build/dist/Types/ServiceLevelObjective/SliType.js.map +1 -0
  372. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js +7 -0
  373. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js.map +1 -0
  374. package/build/dist/Types/ServiceLevelObjective/SloStatus.js +10 -0
  375. package/build/dist/Types/ServiceLevelObjective/SloStatus.js.map +1 -0
  376. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js +7 -0
  377. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js.map +1 -0
  378. package/build/dist/Types/Telemetry/ServiceType.js +1 -0
  379. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  380. package/build/dist/UI/Components/Filters/EntityFilter.js +15 -0
  381. package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
  382. package/build/dist/UI/Components/Filters/FilterViewer.js +19 -4
  383. package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
  384. package/build/dist/UI/Components/List/List.js +1 -1
  385. package/build/dist/UI/Components/List/List.js.map +1 -1
  386. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +235 -89
  387. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  388. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js +96 -0
  389. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js.map +1 -0
  390. package/build/dist/UI/Components/Navbar/NavBar.js +14 -2
  391. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  392. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +3 -2
  393. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  394. package/build/dist/UI/Utils/Navigation.js +9 -0
  395. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  396. package/build/dist/UI/Utils/TableFilterUrlState.js +159 -15
  397. package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
  398. package/build/dist/UI/Utils/TableViewUrlState.js +103 -0
  399. package/build/dist/UI/Utils/TableViewUrlState.js.map +1 -0
  400. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +93 -0
  401. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -0
  402. package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
  403. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  404. package/build/dist/Utils/IpCanonicalUtil.js +110 -0
  405. package/build/dist/Utils/IpCanonicalUtil.js.map +1 -0
  406. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js +311 -0
  407. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js.map +1 -0
  408. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +98 -5
  409. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  410. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +222 -0
  411. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -0
  412. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js +89 -0
  413. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js.map +1 -0
  414. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +60 -0
  415. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -0
  416. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +76 -0
  417. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -0
  418. package/build/dist/Utils/Slo/SloStatusColor.js +18 -0
  419. package/build/dist/Utils/Slo/SloStatusColor.js.map +1 -0
  420. package/build/dist/Utils/Slo/SloUtil.js +393 -0
  421. package/build/dist/Utils/Slo/SloUtil.js.map +1 -0
  422. package/build/dist/Utils/Slo/SloWidgetFormat.js +174 -0
  423. package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -0
  424. package/package.json +2 -2
  425. package/Types/Dashboard/DashboardComponents/Index.ts +0 -7
  426. package/build/dist/Types/Dashboard/DashboardComponents/Index.js +0 -8
  427. package/build/dist/Types/Dashboard/DashboardComponents/Index.js.map +0 -1
@@ -0,0 +1,1038 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import AlertService from "./AlertService";
11
+ import AlertSeverityService from "./AlertSeverityService";
12
+ import AlertStateTimelineService from "./AlertStateTimelineService";
13
+ import DatabaseService from "./DatabaseService";
14
+ import MonitorService from "./MonitorService";
15
+ import MonitorStatusService from "./MonitorStatusService";
16
+ import NetworkDeviceService from "./NetworkDeviceService";
17
+ import NetworkSiteStatusTimelineService from "./NetworkSiteStatusTimelineService";
18
+ import Model from "../../Models/DatabaseModels/NetworkSite";
19
+ import Alert from "../../Models/DatabaseModels/Alert";
20
+ import AlertStateTimeline from "../../Models/DatabaseModels/AlertStateTimeline";
21
+ import NetworkSiteStatusTimeline from "../../Models/DatabaseModels/NetworkSiteStatusTimeline";
22
+ import { DisableAutomaticAlertCreation } from "../EnvironmentConfig";
23
+ import SortOrder from "../../Types/BaseDatabase/SortOrder";
24
+ import QueryHelper from "../Types/Database/QueryHelper";
25
+ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
26
+ import NetworkDeviceHydrationUtil from "../Utils/Monitor/NetworkDeviceHydrationUtil";
27
+ import logger from "../Utils/Logger";
28
+ import LIMIT_MAX, { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
29
+ import BadDataException from "../../Types/Exception/BadDataException";
30
+ import MonitorType from "../../Types/Monitor/MonitorType";
31
+ import ObjectID from "../../Types/ObjectID";
32
+ import OneUptimeDate from "../../Types/Date";
33
+ import Text from "../../Types/Text";
34
+ import { Raw } from "typeorm";
35
+ import MaterializedPathUtil from "../../Utils/NetworkSite/MaterializedPathUtil";
36
+ import SiteStatusRollupUtil from "../../Utils/NetworkSite/SiteStatusRollupUtil";
37
+ export class Service extends DatabaseService {
38
+ constructor() {
39
+ super(Model);
40
+ }
41
+ /*
42
+ * ------------------------------------------------------------------
43
+ * Hierarchy maintenance (materializedPath + depth)
44
+ * ------------------------------------------------------------------
45
+ */
46
+ /*
47
+ * The hierarchy hooks run BEFORE DatabaseService applies tenant scoping to
48
+ * the caller's query (ModelPermission.check*QueryPermissions runs after
49
+ * onBeforeUpdate / onBeforeDelete), so reading the raw client query with
50
+ * props.isRoot would hand the hook rows from other projects - which the
51
+ * success hooks then write. Re-apply the caller's tenant here so a hook can
52
+ * never see, let alone rewrite, a row outside the caller's project.
53
+ */
54
+ scopeQueryToCallerTenant(query, props) {
55
+ if (props.isRoot || !props.tenantId) {
56
+ return query;
57
+ }
58
+ return Object.assign(Object.assign({}, query), { projectId: props.tenantId });
59
+ }
60
+ /*
61
+ * Case-sensitive, un-CAST prefix predicate on materializedPath.
62
+ * QueryHelper.startsWith emits `CAST(alias AS TEXT) ILIKE :x`, and both the
63
+ * cast and the case-insensitive match make the btree index on the column
64
+ * unusable, so every rollup would sequentially scan the table. Paths are
65
+ * built from UUIDs only, so there are no LIKE wildcards to escape.
66
+ */
67
+ pathStartsWith(path) {
68
+ const rid = Text.generateRandomText(10);
69
+ return Raw((alias) => {
70
+ return `(${alias} LIKE :${rid})`;
71
+ }, {
72
+ [rid]: `${path}%`,
73
+ });
74
+ }
75
+ /*
76
+ * A stored path is trustworthy only when it agrees with parentSiteId: it
77
+ * must end with the site's own id, and the segment before it must be the
78
+ * parent (nothing before it for a root). A delete that nulls parentSiteId,
79
+ * or a half-applied move, leaves the two disagreeing - and a stale path
80
+ * silently corrupts every prefix query built from it, so treat it as
81
+ * missing and let the caller rebuild.
82
+ */
83
+ isPathConsistent(site) {
84
+ if (!site.id) {
85
+ return false;
86
+ }
87
+ const segments = MaterializedPathUtil.segmentsOf(site.materializedPath);
88
+ if (segments.length === 0) {
89
+ return false;
90
+ }
91
+ if (segments[segments.length - 1] !== site.id.toString()) {
92
+ return false;
93
+ }
94
+ const parentSegment = segments.length > 1 ? segments[segments.length - 2] : null;
95
+ const parentId = site.parentSiteId
96
+ ? site.parentSiteId.toString()
97
+ : null;
98
+ return parentSegment === parentId;
99
+ }
100
+ async onBeforeCreate(createBy) {
101
+ let parentPath = null;
102
+ if (createBy.data.parentSiteId) {
103
+ const parent = await this.findOneById({
104
+ id: createBy.data.parentSiteId,
105
+ select: {
106
+ _id: true,
107
+ projectId: true,
108
+ },
109
+ props: {
110
+ isRoot: true,
111
+ },
112
+ });
113
+ if (!parent) {
114
+ throw new BadDataException("Parent site not found.");
115
+ }
116
+ if (createBy.data.projectId &&
117
+ parent.projectId &&
118
+ parent.projectId.toString() !== createBy.data.projectId.toString()) {
119
+ throw new BadDataException("Parent site must belong to the same project.");
120
+ }
121
+ parentPath = await this.getMaterializedPathForSite(createBy.data.parentSiteId);
122
+ }
123
+ return {
124
+ createBy: createBy,
125
+ carryForward: {
126
+ parentPath: parentPath,
127
+ },
128
+ };
129
+ }
130
+ async onCreateSuccess(onCreate, createdItem) {
131
+ var _a;
132
+ if (!createdItem.id) {
133
+ return createdItem;
134
+ }
135
+ const parentPath = ((_a = onCreate.carryForward) === null || _a === void 0 ? void 0 : _a.parentPath) || null;
136
+ const path = MaterializedPathUtil.buildPath(parentPath, createdItem.id.toString());
137
+ await this.updateColumnsByIdWithoutHooks({
138
+ id: createdItem.id,
139
+ data: {
140
+ materializedPath: path,
141
+ depth: MaterializedPathUtil.depthOf(path),
142
+ },
143
+ });
144
+ createdItem.materializedPath = path;
145
+ createdItem.depth = MaterializedPathUtil.depthOf(path);
146
+ return createdItem;
147
+ }
148
+ async onBeforeUpdate(updateBy) {
149
+ const dataKeys = Object.keys(updateBy.data || {});
150
+ if (!dataKeys.includes("parentSiteId")) {
151
+ return { updateBy, carryForward: null };
152
+ }
153
+ const newParentIdValue = updateBy.data["parentSiteId"];
154
+ const newParentId = newParentIdValue
155
+ ? new ObjectID(newParentIdValue.toString())
156
+ : null;
157
+ const previousItems = await this.findBy({
158
+ query: this.scopeQueryToCallerTenant(updateBy.query, updateBy.props),
159
+ select: {
160
+ _id: true,
161
+ projectId: true,
162
+ parentSiteId: true,
163
+ materializedPath: true,
164
+ },
165
+ limit: LIMIT_MAX,
166
+ skip: 0,
167
+ props: {
168
+ isRoot: true,
169
+ },
170
+ });
171
+ /*
172
+ * Same-project assertion for EVERY parentSiteId write, including the
173
+ * detach case (parentSiteId: null) which has no parent to compare
174
+ * against: onUpdateSuccess rewrites each matched site's whole subtree, so
175
+ * a site outside the caller's project must never reach it.
176
+ */
177
+ if (updateBy.props.tenantId) {
178
+ for (const item of previousItems) {
179
+ if (item.projectId &&
180
+ item.projectId.toString() !== updateBy.props.tenantId.toString()) {
181
+ throw new BadDataException("Network site must belong to the same project.");
182
+ }
183
+ }
184
+ }
185
+ let newParentPath = null;
186
+ if (newParentId) {
187
+ const parent = await this.findOneById({
188
+ id: newParentId,
189
+ select: {
190
+ _id: true,
191
+ projectId: true,
192
+ },
193
+ props: {
194
+ isRoot: true,
195
+ },
196
+ });
197
+ if (!parent) {
198
+ throw new BadDataException("Parent site not found.");
199
+ }
200
+ for (const item of previousItems) {
201
+ if (item.id && item.id.toString() === newParentId.toString()) {
202
+ throw new BadDataException("A site cannot be its own parent.");
203
+ }
204
+ if (item.projectId &&
205
+ parent.projectId &&
206
+ item.projectId.toString() !== parent.projectId.toString()) {
207
+ throw new BadDataException("Parent site must belong to the same project.");
208
+ }
209
+ }
210
+ newParentPath = await this.getMaterializedPathForSite(newParentId);
211
+ for (const item of previousItems) {
212
+ if (item.id &&
213
+ MaterializedPathUtil.wouldCreateCycle(item.id.toString(), newParentPath)) {
214
+ throw new BadDataException("Cannot move a site under itself or one of its own descendants.");
215
+ }
216
+ }
217
+ }
218
+ const carryForward = {
219
+ previousItems: previousItems,
220
+ newParentId: newParentId,
221
+ newParentPath: newParentPath,
222
+ };
223
+ return { updateBy, carryForward };
224
+ }
225
+ async onUpdateSuccess(onUpdate, updatedItemIds) {
226
+ var _a;
227
+ const parentChange = onUpdate.carryForward || null;
228
+ if (!parentChange) {
229
+ return onUpdate;
230
+ }
231
+ /*
232
+ * DatabaseService calls onUpdateSuccess even when the tenant-scoped
233
+ * UPDATE matched zero rows, so the carried previousItems are not proof
234
+ * that anything was written. Only rows the UPDATE actually matched may be
235
+ * rebased here.
236
+ */
237
+ const updatedIds = new Set(updatedItemIds.map((id) => {
238
+ return id.toString();
239
+ }));
240
+ for (const previousItem of parentChange.previousItems) {
241
+ if (!previousItem.id || !updatedIds.has(previousItem.id.toString())) {
242
+ continue;
243
+ }
244
+ const oldPath = previousItem.materializedPath || null;
245
+ const newPath = MaterializedPathUtil.buildPath(parentChange.newParentPath, previousItem.id.toString());
246
+ if (oldPath === newPath) {
247
+ continue;
248
+ }
249
+ // Rebase the moved site itself...
250
+ await this.updateColumnsByIdWithoutHooks({
251
+ id: previousItem.id,
252
+ data: {
253
+ materializedPath: newPath,
254
+ depth: MaterializedPathUtil.depthOf(newPath),
255
+ },
256
+ });
257
+ // ...then its entire subtree in one prefix query.
258
+ if (oldPath) {
259
+ const descendants = await this.findBy({
260
+ query: {
261
+ projectId: previousItem.projectId,
262
+ materializedPath: this.pathStartsWith(oldPath),
263
+ },
264
+ select: {
265
+ _id: true,
266
+ materializedPath: true,
267
+ },
268
+ limit: LIMIT_MAX,
269
+ skip: 0,
270
+ props: {
271
+ isRoot: true,
272
+ },
273
+ });
274
+ for (const descendant of descendants) {
275
+ if (!descendant.id ||
276
+ !descendant.materializedPath ||
277
+ descendant.id.toString() === previousItem.id.toString()) {
278
+ continue;
279
+ }
280
+ const rebasedPath = MaterializedPathUtil.rebasePaths(oldPath, newPath, [descendant.materializedPath])[0];
281
+ await this.updateColumnsByIdWithoutHooks({
282
+ id: descendant.id,
283
+ data: {
284
+ materializedPath: rebasedPath,
285
+ depth: MaterializedPathUtil.depthOf(rebasedPath),
286
+ },
287
+ });
288
+ }
289
+ }
290
+ /*
291
+ * Moving a subtree changes the rollup of both the new ancestor chain
292
+ * (via the moved site) and the old one (via the old parent). Rollup
293
+ * failures must never fail the move itself - the cron backstop
294
+ * reconciles.
295
+ */
296
+ try {
297
+ await this.recomputeRollupForSiteAndAncestors(previousItem.id);
298
+ if (previousItem.parentSiteId) {
299
+ await this.recomputeRollupForSiteAndAncestors(previousItem.parentSiteId);
300
+ }
301
+ }
302
+ catch (error) {
303
+ logger.error(`NetworkSiteService.onUpdateSuccess: rollup after site move failed for site ${previousItem.id.toString()}: ${error}`, {
304
+ projectId: (_a = previousItem.projectId) === null || _a === void 0 ? void 0 : _a.toString(),
305
+ siteId: previousItem.id.toString(),
306
+ });
307
+ }
308
+ }
309
+ return onUpdate;
310
+ }
311
+ /*
312
+ * Deletes are hard deletes, so the rows' hierarchy state has to be captured
313
+ * before they disappear. Scoped to the caller's tenant for the same reason
314
+ * onBeforeUpdate is: this hook runs before the delete query is permission
315
+ * checked.
316
+ */
317
+ async onBeforeDelete(deleteBy) {
318
+ const sitesToDelete = await this.findBy({
319
+ query: this.scopeQueryToCallerTenant(deleteBy.query, deleteBy.props),
320
+ select: {
321
+ _id: true,
322
+ projectId: true,
323
+ parentSiteId: true,
324
+ materializedPath: true,
325
+ },
326
+ limit: LIMIT_MAX,
327
+ skip: 0,
328
+ props: {
329
+ isRoot: true,
330
+ },
331
+ });
332
+ const carryForward = {
333
+ sitesToDelete: sitesToDelete,
334
+ };
335
+ return { deleteBy, carryForward };
336
+ }
337
+ /*
338
+ * parentSiteId is declared onDelete: "SET NULL", so Postgres detaches the
339
+ * deleted site's direct children but leaves their materializedPath - and
340
+ * their whole subtree's - routed through a row that no longer exists. That
341
+ * strands the subtree: the children endpoint (which reads parentSiteId)
342
+ * shows them at the root while the rollup engine (which reads
343
+ * materializedPath) still folds them into the dead ancestor's chain, double
344
+ * counting every outage. Re-attach the orphans to the deleted site's own
345
+ * parent - NULL when it was a root, which is exactly what the FK did - and
346
+ * rebase the subtree paths so both readers agree again.
347
+ */
348
+ async onDeleteSuccess(onDelete, itemIdsBeforeDelete) {
349
+ const carryForward = onDelete.carryForward || null;
350
+ if (!carryForward) {
351
+ return onDelete;
352
+ }
353
+ // Only rows the permission-checked delete actually removed.
354
+ const deletedIds = new Set(itemIdsBeforeDelete.map((id) => {
355
+ return id.toString();
356
+ }));
357
+ for (const deletedSite of carryForward.sitesToDelete) {
358
+ if (!deletedSite.id ||
359
+ !deletedSite.projectId ||
360
+ !deletedIds.has(deletedSite.id.toString())) {
361
+ continue;
362
+ }
363
+ /*
364
+ * Repair failures must never fail the delete itself - the row is
365
+ * already gone, and getMaterializedPathForSite self-heals a stranded
366
+ * path on next use.
367
+ */
368
+ try {
369
+ await this.reattachOrphanedSubtree(deletedSite);
370
+ }
371
+ catch (error) {
372
+ logger.error(`NetworkSiteService.onDeleteSuccess: subtree repair after deleting site ${deletedSite.id.toString()} failed: ${error}`, {
373
+ projectId: deletedSite.projectId.toString(),
374
+ siteId: deletedSite.id.toString(),
375
+ });
376
+ }
377
+ }
378
+ return onDelete;
379
+ }
380
+ /*
381
+ * Rewrites the deleted site's former subtree so the '/deletedId/' segment
382
+ * is dropped from every path, and re-points its direct children at the
383
+ * deleted site's parent.
384
+ */
385
+ async reattachOrphanedSubtree(deletedSite) {
386
+ const oldPath = deletedSite.materializedPath || null;
387
+ if (!oldPath || !deletedSite.id) {
388
+ return;
389
+ }
390
+ const parentPath = deletedSite.parentSiteId
391
+ ? await this.getMaterializedPathForSite(deletedSite.parentSiteId)
392
+ : null;
393
+ const deletedDepth = MaterializedPathUtil.segmentsOf(oldPath).length;
394
+ const descendants = await this.findBy({
395
+ query: {
396
+ projectId: deletedSite.projectId,
397
+ materializedPath: this.pathStartsWith(oldPath),
398
+ },
399
+ select: {
400
+ _id: true,
401
+ materializedPath: true,
402
+ },
403
+ limit: LIMIT_MAX,
404
+ skip: 0,
405
+ props: {
406
+ isRoot: true,
407
+ },
408
+ });
409
+ for (const descendant of descendants) {
410
+ if (!descendant.id ||
411
+ !descendant.materializedPath ||
412
+ descendant.id.toString() === deletedSite.id.toString()) {
413
+ continue;
414
+ }
415
+ const tailSegments = MaterializedPathUtil.segmentsOf(descendant.materializedPath).slice(deletedDepth);
416
+ if (tailSegments.length === 0) {
417
+ continue;
418
+ }
419
+ let rebasedPath = parentPath;
420
+ for (const segment of tailSegments) {
421
+ rebasedPath = MaterializedPathUtil.buildPath(rebasedPath, segment);
422
+ }
423
+ const data = {
424
+ materializedPath: rebasedPath,
425
+ depth: MaterializedPathUtil.depthOf(rebasedPath),
426
+ };
427
+ // A direct child is the one the FK just detached - give it a parent back.
428
+ if (tailSegments.length === 1) {
429
+ data["parentSiteId"] = deletedSite.parentSiteId || null;
430
+ }
431
+ await this.updateColumnsByIdWithoutHooks({
432
+ id: descendant.id,
433
+ data: data,
434
+ });
435
+ }
436
+ /*
437
+ * The deleted site's own devices were detached by their FK too, so the
438
+ * surviving ancestor chain's rollup is now stale.
439
+ */
440
+ if (deletedSite.parentSiteId) {
441
+ await this.recomputeRollupForSiteAndAncestors(deletedSite.parentSiteId);
442
+ }
443
+ }
444
+ /*
445
+ * Returns the site's materialized path, rebuilding (and persisting) it by
446
+ * walking up the parent chain when the stored value is missing OR no longer
447
+ * agrees with parentSiteId - a row created before path maintenance existed,
448
+ * one whose maintenance write failed, or one stranded by a deleted
449
+ * ancestor, self-heals on first use.
450
+ */
451
+ async getMaterializedPathForSite(siteId) {
452
+ var _a;
453
+ const site = await this.findOneById({
454
+ id: siteId,
455
+ select: {
456
+ _id: true,
457
+ parentSiteId: true,
458
+ materializedPath: true,
459
+ },
460
+ props: {
461
+ isRoot: true,
462
+ },
463
+ });
464
+ if (!site || !site.id) {
465
+ return null;
466
+ }
467
+ if (site.materializedPath && this.isPathConsistent(site)) {
468
+ return site.materializedPath;
469
+ }
470
+ /*
471
+ * Walk up until a parent with a stored path (or a root) is found. The
472
+ * visited set guards against pre-existing cycles in the data - without
473
+ * it a corrupted parent chain would loop forever.
474
+ */
475
+ const chain = [site];
476
+ const visited = new Set([site.id.toString()]);
477
+ let prefixPath = null;
478
+ let cursor = site;
479
+ while (cursor.parentSiteId) {
480
+ if (visited.has(cursor.parentSiteId.toString())) {
481
+ logger.error(`NetworkSiteService.getMaterializedPathForSite: cycle detected in parent chain of site ${siteId.toString()}; treating ${(_a = cursor.id) === null || _a === void 0 ? void 0 : _a.toString()} as a root.`);
482
+ break;
483
+ }
484
+ const parent = await this.findOneById({
485
+ id: cursor.parentSiteId,
486
+ select: {
487
+ _id: true,
488
+ parentSiteId: true,
489
+ materializedPath: true,
490
+ },
491
+ props: {
492
+ isRoot: true,
493
+ },
494
+ });
495
+ if (!parent || !parent.id) {
496
+ break;
497
+ }
498
+ // A stale ancestor path would poison every path rebuilt from it.
499
+ if (parent.materializedPath && this.isPathConsistent(parent)) {
500
+ prefixPath = parent.materializedPath;
501
+ break;
502
+ }
503
+ visited.add(parent.id.toString());
504
+ chain.push(parent);
505
+ cursor = parent;
506
+ }
507
+ // Fold back down, persisting the healed paths as we go.
508
+ let path = prefixPath;
509
+ for (let i = chain.length - 1; i >= 0; i--) {
510
+ const chainSite = chain[i];
511
+ path = MaterializedPathUtil.buildPath(path, chainSite.id.toString());
512
+ await this.updateColumnsByIdWithoutHooks({
513
+ id: chainSite.id,
514
+ data: {
515
+ materializedPath: path,
516
+ depth: MaterializedPathUtil.depthOf(path),
517
+ },
518
+ });
519
+ }
520
+ return path;
521
+ }
522
+ // Ancestor IDs from root to direct parent (excludes the site itself).
523
+ async getAncestorIds(siteId) {
524
+ const path = await this.getMaterializedPathForSite(siteId);
525
+ if (!path) {
526
+ return [];
527
+ }
528
+ return MaterializedPathUtil.segmentsOf(path)
529
+ .filter((segment) => {
530
+ return segment !== siteId.toString();
531
+ })
532
+ .map((segment) => {
533
+ return new ObjectID(segment);
534
+ });
535
+ }
536
+ /*
537
+ * Strict descendant IDs (excludes the site itself), via path prefix query.
538
+ * projectId is required by every production caller: without it the prefix
539
+ * scan has no indexable predicate and reads every tenant's rows.
540
+ */
541
+ async getDescendantSiteIds(siteId, projectId) {
542
+ const path = await this.getMaterializedPathForSite(siteId);
543
+ if (!path) {
544
+ return [];
545
+ }
546
+ const query = {
547
+ materializedPath: this.pathStartsWith(path),
548
+ };
549
+ if (projectId) {
550
+ query.projectId = projectId;
551
+ }
552
+ const descendants = await this.findBy({
553
+ query: query,
554
+ select: {
555
+ _id: true,
556
+ },
557
+ limit: LIMIT_MAX,
558
+ skip: 0,
559
+ props: {
560
+ isRoot: true,
561
+ },
562
+ });
563
+ return descendants
564
+ .filter((descendant) => {
565
+ return descendant.id && descendant.id.toString() !== siteId.toString();
566
+ })
567
+ .map((descendant) => {
568
+ return descendant.id;
569
+ });
570
+ }
571
+ /*
572
+ * ------------------------------------------------------------------
573
+ * Persisted rollup engine
574
+ * ------------------------------------------------------------------
575
+ */
576
+ /*
577
+ * Recomputes the worst-of rollup for one site from the devices in its
578
+ * subtree, persisting currentMonitorStatusId + lastRollupAt and keeping
579
+ * the NetworkSiteStatusTimeline in sync (close the open row, open a new
580
+ * one) whenever the status actually changes.
581
+ */
582
+ async recomputeRollupForSite(siteId) {
583
+ var _a;
584
+ const site = await this.findOneById({
585
+ id: siteId,
586
+ select: {
587
+ _id: true,
588
+ projectId: true,
589
+ currentMonitorStatusId: true,
590
+ name: true,
591
+ shouldAlertWhenUnhealthy: true,
592
+ alertSeverityId: true,
593
+ currentActiveAlertId: true,
594
+ },
595
+ props: {
596
+ isRoot: true,
597
+ },
598
+ });
599
+ if (!site || !site.id || !site.projectId) {
600
+ return;
601
+ }
602
+ const subtreeSiteIds = [
603
+ site.id,
604
+ ...(await this.getDescendantSiteIds(site.id, site.projectId)),
605
+ ];
606
+ /*
607
+ * Archived devices are decommissioned: they keep their siteId but must
608
+ * not vote in the rollup. An archived, never-monitored device otherwise
609
+ * falls through to the freshness fallback (stale lastSeenAt -> Offline)
610
+ * and pins its whole ancestor chain red forever, with the drill-down
611
+ * showing zero devices because that query excludes archived rows.
612
+ */
613
+ const devices = await NetworkDeviceService.findBy({
614
+ query: {
615
+ projectId: site.projectId,
616
+ siteId: QueryHelper.any(subtreeSiteIds),
617
+ isArchived: false,
618
+ },
619
+ select: {
620
+ _id: true,
621
+ currentMonitorStatusId: true,
622
+ lastSeenAt: true,
623
+ },
624
+ limit: LIMIT_MAX,
625
+ skip: 0,
626
+ props: {
627
+ isRoot: true,
628
+ },
629
+ });
630
+ const statuses = await MonitorStatusService.findBy({
631
+ query: {
632
+ projectId: site.projectId,
633
+ },
634
+ select: {
635
+ _id: true,
636
+ name: true,
637
+ priority: true,
638
+ isOperationalState: true,
639
+ isOfflineState: true,
640
+ },
641
+ limit: LIMIT_PER_PROJECT,
642
+ skip: 0,
643
+ props: {
644
+ isRoot: true,
645
+ },
646
+ });
647
+ const priorityByStatusId = new Map();
648
+ let operationalStatus = null;
649
+ let offlineStatus = null;
650
+ for (const status of statuses) {
651
+ if (!status.id || typeof status.priority !== "number") {
652
+ continue;
653
+ }
654
+ priorityByStatusId.set(status.id.toString(), status.priority);
655
+ if (status.isOperationalState && !operationalStatus) {
656
+ operationalStatus = {
657
+ monitorStatusId: status.id.toString(),
658
+ priority: status.priority,
659
+ };
660
+ }
661
+ if (status.isOfflineState && !offlineStatus) {
662
+ offlineStatus = {
663
+ monitorStatusId: status.id.toString(),
664
+ priority: status.priority,
665
+ };
666
+ }
667
+ }
668
+ const deviceStates = devices.map((device) => {
669
+ var _a;
670
+ const statusId = (_a = device.currentMonitorStatusId) === null || _a === void 0 ? void 0 : _a.toString();
671
+ return {
672
+ currentMonitorStatusId: statusId,
673
+ monitorStatusPriority: statusId
674
+ ? priorityByStatusId.get(statusId)
675
+ : undefined,
676
+ lastSeenAt: device.lastSeenAt,
677
+ };
678
+ });
679
+ const worstStatusId = SiteStatusRollupUtil.worstStatus({
680
+ deviceStates: deviceStates,
681
+ operationalStatus: operationalStatus,
682
+ offlineStatus: offlineStatus,
683
+ });
684
+ const now = OneUptimeDate.getCurrentDate();
685
+ const currentStatusId = ((_a = site.currentMonitorStatusId) === null || _a === void 0 ? void 0 : _a.toString()) || null;
686
+ // No devices contribute -> leave the status alone, just stamp the run.
687
+ if (!worstStatusId || worstStatusId === currentStatusId) {
688
+ await this.updateColumnsByIdWithoutHooks({
689
+ id: site.id,
690
+ data: {
691
+ lastRollupAt: now,
692
+ },
693
+ });
694
+ return;
695
+ }
696
+ await this.updateColumnsByIdWithoutHooks({
697
+ id: site.id,
698
+ data: {
699
+ currentMonitorStatusId: new ObjectID(worstStatusId),
700
+ lastRollupAt: now,
701
+ },
702
+ });
703
+ // Close every open timeline row, then open one for the new status.
704
+ await NetworkSiteStatusTimelineService.updateBy({
705
+ query: {
706
+ siteId: site.id,
707
+ endsAt: QueryHelper.isNull(),
708
+ },
709
+ data: {
710
+ endsAt: now,
711
+ },
712
+ limit: LIMIT_MAX,
713
+ skip: 0,
714
+ props: {
715
+ isRoot: true,
716
+ },
717
+ });
718
+ const timeline = new NetworkSiteStatusTimeline();
719
+ timeline.projectId = site.projectId;
720
+ timeline.siteId = site.id;
721
+ timeline.monitorStatusId = new ObjectID(worstStatusId);
722
+ timeline.startsAt = now;
723
+ await NetworkSiteStatusTimelineService.create({
724
+ data: timeline,
725
+ props: {
726
+ isRoot: true,
727
+ },
728
+ });
729
+ /*
730
+ * Site alerting rides the same transition the timeline records. Alert
731
+ * bookkeeping must never break the rollup itself.
732
+ */
733
+ try {
734
+ await this.syncSiteAlertForStatusTransition({
735
+ site: site,
736
+ newStatus: statuses.find((status) => {
737
+ var _a;
738
+ return ((_a = status.id) === null || _a === void 0 ? void 0 : _a.toString()) === worstStatusId;
739
+ }) || null,
740
+ });
741
+ }
742
+ catch (err) {
743
+ logger.error(`Network site rollup: error syncing alert for site ${site.id.toString()}:`);
744
+ logger.error(err);
745
+ }
746
+ }
747
+ /*
748
+ * Opens an alert when a site's rollup TRANSITIONS to a non-operational
749
+ * status (and alerting is enabled on the site), and auto-resolves that
750
+ * alert when the site transitions back to operational. Transition-only
751
+ * by design: enabling alerting on an already-unhealthy site arms the
752
+ * next transition instead of retro-alerting, and a manually resolved
753
+ * alert is not reopened until the site recovers and degrades again
754
+ * (a transition clears the tracked id).
755
+ */
756
+ async syncSiteAlertForStatusTransition(data) {
757
+ const site = data.site;
758
+ if (!site.id || !site.projectId || !data.newStatus) {
759
+ return;
760
+ }
761
+ const isNowOperational = Boolean(data.newStatus.isOperationalState);
762
+ // Recovery: resolve the open site alert, if one is tracked.
763
+ if (isNowOperational) {
764
+ if (!site.currentActiveAlertId) {
765
+ return;
766
+ }
767
+ await this.resolveSiteAlert({
768
+ projectId: site.projectId,
769
+ alertId: site.currentActiveAlertId,
770
+ rootCause: `**Recovered:** Network site **${site.name || "site"}** rolled back up to ${data.newStatus.name || "an operational status"}.`,
771
+ });
772
+ await this.updateColumnsByIdWithoutHooks({
773
+ id: site.id,
774
+ data: {
775
+ currentActiveAlertId: null,
776
+ },
777
+ });
778
+ return;
779
+ }
780
+ // Degradation between two unhealthy statuses keeps the existing alert.
781
+ if (!site.shouldAlertWhenUnhealthy ||
782
+ site.currentActiveAlertId ||
783
+ DisableAutomaticAlertCreation) {
784
+ return;
785
+ }
786
+ let alertSeverityId = site.alertSeverityId;
787
+ if (!alertSeverityId) {
788
+ // Same default the monitor alert path uses: the most severe first.
789
+ const severity = await AlertSeverityService.findOneBy({
790
+ query: {
791
+ projectId: site.projectId,
792
+ },
793
+ sort: {
794
+ order: SortOrder.Ascending,
795
+ },
796
+ select: {
797
+ _id: true,
798
+ },
799
+ props: {
800
+ isRoot: true,
801
+ },
802
+ });
803
+ if (!severity || !severity.id) {
804
+ logger.warn(`Network site alerting: project ${site.projectId.toString()} has no alert severity; skipping site alert.`);
805
+ return;
806
+ }
807
+ alertSeverityId = severity.id;
808
+ }
809
+ const statusName = data.newStatus.name || "Unhealthy";
810
+ const alert = new Alert();
811
+ alert.projectId = site.projectId;
812
+ alert.title = `Network site ${site.name || site.id.toString()} is ${statusName}`;
813
+ alert.description = `The health rollup of network site **${site.name || site.id.toString()}** changed to **${statusName}** — the worst status of the devices at this site and every site below it. This alert auto-resolves when the site rolls back up to an operational status.`;
814
+ alert.alertSeverityId = alertSeverityId;
815
+ alert.rootCause = `Network site **${site.name || site.id.toString()}** rolled up to **${statusName}**.`;
816
+ const createdAlert = await AlertService.create({
817
+ data: alert,
818
+ props: {
819
+ isRoot: true,
820
+ },
821
+ });
822
+ if (createdAlert.id) {
823
+ await this.updateColumnsByIdWithoutHooks({
824
+ id: site.id,
825
+ data: {
826
+ currentActiveAlertId: createdAlert.id,
827
+ },
828
+ });
829
+ }
830
+ }
831
+ // Moves a site alert to the project's resolved state, if not already there.
832
+ async resolveSiteAlert(data) {
833
+ var _a;
834
+ const alert = await AlertService.findOneById({
835
+ id: data.alertId,
836
+ select: {
837
+ _id: true,
838
+ currentAlertStateId: true,
839
+ },
840
+ props: {
841
+ isRoot: true,
842
+ },
843
+ });
844
+ if (!alert || !alert.id) {
845
+ // Deleted by hand — nothing to resolve.
846
+ return;
847
+ }
848
+ const resolvedStateId = await AlertStateTimelineService.getResolvedStateIdForProject(data.projectId);
849
+ if (((_a = alert.currentAlertStateId) === null || _a === void 0 ? void 0 : _a.toString()) === resolvedStateId.toString()) {
850
+ // Already resolved manually.
851
+ return;
852
+ }
853
+ const alertStateTimeline = new AlertStateTimeline();
854
+ alertStateTimeline.alertId = alert.id;
855
+ alertStateTimeline.alertStateId = resolvedStateId;
856
+ alertStateTimeline.projectId = data.projectId;
857
+ alertStateTimeline.rootCause = data.rootCause;
858
+ await AlertStateTimelineService.create({
859
+ data: alertStateTimeline,
860
+ props: {
861
+ isRoot: true,
862
+ },
863
+ });
864
+ }
865
+ // Recomputes the site itself, then each ancestor (nearest first).
866
+ async recomputeRollupForSiteAndAncestors(siteId) {
867
+ await this.recomputeRollupForSite(siteId);
868
+ const ancestorIds = await this.getAncestorIds(siteId);
869
+ // getAncestorIds returns root-first; recompute nearest ancestor first.
870
+ for (let i = ancestorIds.length - 1; i >= 0; i--) {
871
+ await this.recomputeRollupForSite(ancestorIds[i]);
872
+ }
873
+ }
874
+ /*
875
+ * ------------------------------------------------------------------
876
+ * Monitor status bridge
877
+ * ------------------------------------------------------------------
878
+ */
879
+ /*
880
+ * Called by MonitorService.changeMonitorStatus after a status persists.
881
+ * Resolves which NetworkDevices the monitors reference in their steps,
882
+ * stamps those devices' currentMonitorStatusId, then recomputes the
883
+ * rollup for every affected site chain. Never throws - a rollup failure
884
+ * must never break a monitor status change.
885
+ */
886
+ async onMonitorStatusChanged(data) {
887
+ try {
888
+ if (data.monitorIds.length === 0) {
889
+ return;
890
+ }
891
+ const monitors = await MonitorService.findBy({
892
+ query: {
893
+ _id: QueryHelper.any(data.monitorIds),
894
+ projectId: data.projectId,
895
+ monitorType: MonitorType.NetworkDevice,
896
+ },
897
+ select: {
898
+ _id: true,
899
+ monitorType: true,
900
+ monitorSteps: true,
901
+ },
902
+ limit: LIMIT_MAX,
903
+ skip: 0,
904
+ props: {
905
+ isRoot: true,
906
+ },
907
+ });
908
+ if (monitors.length === 0) {
909
+ return;
910
+ }
911
+ const deviceIds = NetworkDeviceHydrationUtil.getReferencedNetworkDeviceIds(monitors);
912
+ if (deviceIds.length === 0) {
913
+ return;
914
+ }
915
+ const devices = await NetworkDeviceService.findBy({
916
+ query: {
917
+ _id: QueryHelper.any(deviceIds),
918
+ projectId: data.projectId,
919
+ },
920
+ select: {
921
+ _id: true,
922
+ siteId: true,
923
+ },
924
+ limit: LIMIT_MAX,
925
+ skip: 0,
926
+ props: {
927
+ isRoot: true,
928
+ },
929
+ });
930
+ for (const device of devices) {
931
+ if (!device.id) {
932
+ continue;
933
+ }
934
+ await NetworkDeviceService.updateColumnsByIdWithoutHooks({
935
+ id: device.id,
936
+ data: {
937
+ currentMonitorStatusId: data.monitorStatusId,
938
+ },
939
+ });
940
+ }
941
+ const distinctSiteIds = new Map();
942
+ for (const device of devices) {
943
+ if (device.siteId) {
944
+ distinctSiteIds.set(device.siteId.toString(), device.siteId);
945
+ }
946
+ }
947
+ for (const siteId of distinctSiteIds.values()) {
948
+ await this.recomputeRollupForSiteAndAncestors(siteId);
949
+ }
950
+ }
951
+ catch (error) {
952
+ logger.error(`NetworkSiteService.onMonitorStatusChanged: failed to update network site rollups: ${error}`, {
953
+ projectId: data.projectId.toString(),
954
+ monitorStatusId: data.monitorStatusId.toString(),
955
+ });
956
+ }
957
+ }
958
+ }
959
+ __decorate([
960
+ CaptureSpan(),
961
+ __metadata("design:type", Function),
962
+ __metadata("design:paramtypes", [Object]),
963
+ __metadata("design:returntype", Promise)
964
+ ], Service.prototype, "onBeforeCreate", null);
965
+ __decorate([
966
+ CaptureSpan(),
967
+ __metadata("design:type", Function),
968
+ __metadata("design:paramtypes", [Object, Model]),
969
+ __metadata("design:returntype", Promise)
970
+ ], Service.prototype, "onCreateSuccess", null);
971
+ __decorate([
972
+ CaptureSpan(),
973
+ __metadata("design:type", Function),
974
+ __metadata("design:paramtypes", [Object]),
975
+ __metadata("design:returntype", Promise)
976
+ ], Service.prototype, "onBeforeUpdate", null);
977
+ __decorate([
978
+ CaptureSpan(),
979
+ __metadata("design:type", Function),
980
+ __metadata("design:paramtypes", [Object, Array]),
981
+ __metadata("design:returntype", Promise)
982
+ ], Service.prototype, "onUpdateSuccess", null);
983
+ __decorate([
984
+ CaptureSpan(),
985
+ __metadata("design:type", Function),
986
+ __metadata("design:paramtypes", [Object]),
987
+ __metadata("design:returntype", Promise)
988
+ ], Service.prototype, "onBeforeDelete", null);
989
+ __decorate([
990
+ CaptureSpan(),
991
+ __metadata("design:type", Function),
992
+ __metadata("design:paramtypes", [Object, Array]),
993
+ __metadata("design:returntype", Promise)
994
+ ], Service.prototype, "onDeleteSuccess", null);
995
+ __decorate([
996
+ CaptureSpan(),
997
+ __metadata("design:type", Function),
998
+ __metadata("design:paramtypes", [ObjectID]),
999
+ __metadata("design:returntype", Promise)
1000
+ ], Service.prototype, "getMaterializedPathForSite", null);
1001
+ __decorate([
1002
+ CaptureSpan(),
1003
+ __metadata("design:type", Function),
1004
+ __metadata("design:paramtypes", [ObjectID]),
1005
+ __metadata("design:returntype", Promise)
1006
+ ], Service.prototype, "getAncestorIds", null);
1007
+ __decorate([
1008
+ CaptureSpan(),
1009
+ __metadata("design:type", Function),
1010
+ __metadata("design:paramtypes", [ObjectID, Object]),
1011
+ __metadata("design:returntype", Promise)
1012
+ ], Service.prototype, "getDescendantSiteIds", null);
1013
+ __decorate([
1014
+ CaptureSpan(),
1015
+ __metadata("design:type", Function),
1016
+ __metadata("design:paramtypes", [ObjectID]),
1017
+ __metadata("design:returntype", Promise)
1018
+ ], Service.prototype, "recomputeRollupForSite", null);
1019
+ __decorate([
1020
+ CaptureSpan(),
1021
+ __metadata("design:type", Function),
1022
+ __metadata("design:paramtypes", [Object]),
1023
+ __metadata("design:returntype", Promise)
1024
+ ], Service.prototype, "syncSiteAlertForStatusTransition", null);
1025
+ __decorate([
1026
+ CaptureSpan(),
1027
+ __metadata("design:type", Function),
1028
+ __metadata("design:paramtypes", [ObjectID]),
1029
+ __metadata("design:returntype", Promise)
1030
+ ], Service.prototype, "recomputeRollupForSiteAndAncestors", null);
1031
+ __decorate([
1032
+ CaptureSpan(),
1033
+ __metadata("design:type", Function),
1034
+ __metadata("design:paramtypes", [Object]),
1035
+ __metadata("design:returntype", Promise)
1036
+ ], Service.prototype, "onMonitorStatusChanged", null);
1037
+ export default new Service();
1038
+ //# sourceMappingURL=NetworkSiteService.js.map