@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,275 @@
1
+ import buildQueryFromFilterData, {
2
+ getFilterKeys,
3
+ sanitizeFilterData,
4
+ } from "../../../../UI/Components/ModelTable/FilterDataToQuery";
5
+ import Filter from "../../../../UI/Components/ModelFilter/Filter";
6
+ import FieldType from "../../../../UI/Components/Types/FieldType";
7
+ import Monitor from "../../../../Models/DatabaseModels/Monitor";
8
+ import Includes from "../../../../Types/BaseDatabase/Includes";
9
+ import IncludesNone from "../../../../Types/BaseDatabase/IncludesNone";
10
+ import InBetween from "../../../../Types/BaseDatabase/InBetween";
11
+ import IsNull from "../../../../Types/BaseDatabase/IsNull";
12
+ import NotEqual from "../../../../Types/BaseDatabase/NotEqual";
13
+ import Search from "../../../../Types/BaseDatabase/Search";
14
+ import Query from "../../../../Types/BaseDatabase/Query";
15
+ import FilterData from "../../../../UI/Components/Filters/Types/FilterData";
16
+ import { describe, expect, test } from "@jest/globals";
17
+
18
+ /*
19
+ * `buildQueryFromFilterData` is what turns the filter popup's selections into
20
+ * the query the table fetches with. It lives outside the component so the
21
+ * table can derive its query *synchronously during the first render* when
22
+ * filters come back from the URL — without that, the first request would go
23
+ * out unfiltered and be immediately superseded, flashing the wrong rows.
24
+ *
25
+ * `sanitizeFilterData` is the trust boundary for that same path: the snapshot
26
+ * arrives from a query string anyone can edit.
27
+ */
28
+
29
+ const FILTERS: Array<Filter<Monitor>> = [
30
+ { title: "Name", type: FieldType.Text, field: { name: true } },
31
+ {
32
+ title: "Description",
33
+ type: FieldType.Text,
34
+ field: { description: true },
35
+ },
36
+ {
37
+ title: "Monitoring disabled",
38
+ type: FieldType.Boolean,
39
+ field: { disableActiveMonitoring: true },
40
+ },
41
+ { title: "Created", type: FieldType.Date, field: { createdAt: true } },
42
+ { title: "Labels", type: FieldType.EntityArray, field: { labels: true } },
43
+ {
44
+ title: "Custom fields",
45
+ type: FieldType.JSON,
46
+ field: { customFields: true },
47
+ },
48
+ ] as unknown as Array<Filter<Monitor>>;
49
+
50
+ type BuildFunction = (filterData: FilterData<Monitor>) => Query<Monitor>;
51
+
52
+ const build: BuildFunction = (
53
+ filterData: FilterData<Monitor>,
54
+ ): Query<Monitor> => {
55
+ return buildQueryFromFilterData<Monitor>({
56
+ filterData: filterData,
57
+ filters: FILTERS,
58
+ });
59
+ };
60
+
61
+ describe("getFilterKeys", () => {
62
+ test("returns the model field behind each declared filter", () => {
63
+ expect(getFilterKeys<Monitor>(FILTERS)).toEqual([
64
+ "name",
65
+ "description",
66
+ "disableActiveMonitoring",
67
+ "createdAt",
68
+ "labels",
69
+ "customFields",
70
+ ]);
71
+ });
72
+
73
+ test("tolerates an empty or missing filter list", () => {
74
+ expect(getFilterKeys<Monitor>([])).toEqual([]);
75
+ expect(
76
+ getFilterKeys<Monitor>(undefined as unknown as Array<Filter<Monitor>>),
77
+ ).toEqual([]);
78
+ });
79
+ });
80
+
81
+ describe("buildQueryFromFilterData", () => {
82
+ test("returns an empty query for no filters", () => {
83
+ expect(build({})).toEqual({});
84
+ });
85
+
86
+ test("passes a text value through", () => {
87
+ expect(build({ name: "api" } as FilterData<Monitor>)).toEqual({
88
+ name: "api",
89
+ });
90
+ });
91
+
92
+ test("keeps a false boolean — it is a real constraint, not an absent one", () => {
93
+ expect(
94
+ build({
95
+ disableActiveMonitoring: false,
96
+ } as unknown as FilterData<Monitor>),
97
+ ).toEqual({ disableActiveMonitoring: false });
98
+ });
99
+
100
+ test("keeps a zero number", () => {
101
+ const query: Query<Monitor> = build({
102
+ name: 0,
103
+ } as unknown as FilterData<Monitor>);
104
+
105
+ expect(query).toEqual({ name: 0 });
106
+ });
107
+
108
+ test("passes a Date through unchanged", () => {
109
+ const date: Date = new Date("2026-07-01T12:34:56.789Z");
110
+
111
+ expect(
112
+ build({ createdAt: date } as unknown as FilterData<Monitor>)["createdAt"],
113
+ ).toBe(date);
114
+ });
115
+
116
+ test("passes a Search through unchanged", () => {
117
+ const search: Search<string> = new Search("api");
118
+
119
+ expect(
120
+ build({ name: search } as unknown as FilterData<Monitor>)["name"],
121
+ ).toBe(search);
122
+ });
123
+
124
+ test("passes an InBetween through unchanged", () => {
125
+ const range: InBetween<Date> = new InBetween(
126
+ new Date("2026-01-01T00:00:00.000Z"),
127
+ new Date("2026-02-01T00:00:00.000Z"),
128
+ );
129
+
130
+ expect(
131
+ build({ createdAt: range } as unknown as FilterData<Monitor>)[
132
+ "createdAt"
133
+ ],
134
+ ).toBe(range);
135
+ });
136
+
137
+ test("wraps a bare array into an Includes", () => {
138
+ const query: Query<Monitor> = build({
139
+ labels: ["a", "b"],
140
+ } as unknown as FilterData<Monitor>);
141
+
142
+ expect(query["labels"]).toBeInstanceOf(Includes);
143
+ expect((query["labels"] as Includes).values).toEqual(["a", "b"]);
144
+ });
145
+
146
+ test("passes any QueryOperator through as-is", () => {
147
+ const operators: Record<string, unknown> = {
148
+ includesNone: new IncludesNone(["a"]),
149
+ isNull: new IsNull(),
150
+ notEqual: new NotEqual("api"),
151
+ };
152
+
153
+ for (const operator of Object.values(operators)) {
154
+ expect(
155
+ build({ name: operator } as unknown as FilterData<Monitor>)["name"],
156
+ ).toBe(operator);
157
+ }
158
+ });
159
+
160
+ test("passes a plain object through only for a JSON-typed filter", () => {
161
+ const value: Record<string, string> = { team: "platform" };
162
+
163
+ expect(
164
+ build({ customFields: value } as unknown as FilterData<Monitor>)[
165
+ "customFields"
166
+ ],
167
+ ).toBe(value);
168
+ });
169
+
170
+ test("drops a plain object on a non-JSON filter", () => {
171
+ expect(
172
+ build({ name: { nope: true } } as unknown as FilterData<Monitor>),
173
+ ).toEqual({});
174
+ });
175
+
176
+ test("drops an empty string — an empty text box is not a filter", () => {
177
+ expect(build({ name: "" } as unknown as FilterData<Monitor>)).toEqual({});
178
+ });
179
+
180
+ test("builds every kind of value in one pass", () => {
181
+ const query: Query<Monitor> = build({
182
+ name: new Search("api"),
183
+ disableActiveMonitoring: false,
184
+ labels: ["a"],
185
+ } as unknown as FilterData<Monitor>);
186
+
187
+ expect(query["name"]).toBeInstanceOf(Search);
188
+ expect(query["disableActiveMonitoring"]).toBe(false);
189
+ expect(query["labels"]).toBeInstanceOf(Includes);
190
+ });
191
+ });
192
+
193
+ describe("sanitizeFilterData", () => {
194
+ type SanitizeFunction = (
195
+ filterData: FilterData<Monitor>,
196
+ ) => FilterData<Monitor>;
197
+
198
+ const sanitize: SanitizeFunction = (
199
+ filterData: FilterData<Monitor>,
200
+ ): FilterData<Monitor> => {
201
+ return sanitizeFilterData<Monitor>({
202
+ filterData: filterData,
203
+ filters: FILTERS,
204
+ });
205
+ };
206
+
207
+ test("keeps every field the table declares a filter for", () => {
208
+ expect(
209
+ sanitize({ name: "api", description: "prod" } as FilterData<Monitor>),
210
+ ).toEqual({ name: "api", description: "prod" });
211
+ });
212
+
213
+ test("drops a field the table does not expose a filter for", () => {
214
+ /*
215
+ * The restored filter is spread into the outgoing list query, so an
216
+ * undeclared key in a hand-edited link would otherwise become a real
217
+ * constraint the filter UI could never have produced.
218
+ */
219
+ expect(
220
+ sanitize({
221
+ name: "api",
222
+ projectId: "somebody-elses-project",
223
+ } as unknown as FilterData<Monitor>),
224
+ ).toEqual({ name: "api" });
225
+ });
226
+
227
+ test("drops a key that tries to re-scope the page's own query", () => {
228
+ expect(
229
+ sanitize({
230
+ monitorId: "another-monitor",
231
+ _id: "specific-row",
232
+ } as unknown as FilterData<Monitor>),
233
+ ).toEqual({});
234
+ });
235
+
236
+ test("drops null and undefined values", () => {
237
+ expect(
238
+ sanitize({
239
+ name: "api",
240
+ description: undefined,
241
+ createdAt: null,
242
+ } as unknown as FilterData<Monitor>),
243
+ ).toEqual({ name: "api" });
244
+ });
245
+
246
+ test("keeps a false boolean", () => {
247
+ expect(
248
+ sanitize({
249
+ disableActiveMonitoring: false,
250
+ } as unknown as FilterData<Monitor>),
251
+ ).toEqual({ disableActiveMonitoring: false });
252
+ });
253
+
254
+ test("keeps typed operator instances intact", () => {
255
+ const search: Search<string> = new Search("api");
256
+
257
+ expect(
258
+ sanitize({ name: search } as unknown as FilterData<Monitor>)["name"],
259
+ ).toBe(search);
260
+ });
261
+
262
+ test("returns an empty object when the table declares no filters at all", () => {
263
+ expect(
264
+ sanitizeFilterData<Monitor>({
265
+ filterData: { name: "api" } as FilterData<Monitor>,
266
+ filters: [],
267
+ }),
268
+ ).toEqual({});
269
+ });
270
+
271
+ test("tolerates an empty snapshot", () => {
272
+ expect(sanitize({})).toEqual({});
273
+ expect(sanitize(undefined as unknown as FilterData<Monitor>)).toEqual({});
274
+ });
275
+ });
@@ -0,0 +1,159 @@
1
+ import Log from "../../../Models/AnalyticsModels/Log";
2
+ import { JSONObject } from "../../../Types/JSON";
3
+ import { exportLogsToCSV, exportLogsToJSON } from "../../../UI/Utils/LogExport";
4
+ import { describe, expect, test } from "@jest/globals";
5
+
6
+ /*
7
+ * LogExport turns a set of Log rows + selected columns into CSV/JSON that the
8
+ * user downloads. The two pure serializers are what these tests guard:
9
+ *
10
+ * - CSV escaping (RFC-4180 style: quote fields containing comma/quote/newline,
11
+ * double embedded quotes) — a bug here corrupts every exported file.
12
+ * - Column resolution, including the "attribute:<key>" dynamic columns that
13
+ * read out of the log's attributes bag.
14
+ */
15
+
16
+ function makeLog(fields: {
17
+ time?: Date;
18
+ body?: string;
19
+ traceId?: string;
20
+ spanId?: string;
21
+ severityText?: string;
22
+ attributes?: JSONObject;
23
+ }): Log {
24
+ const log: Log = new Log();
25
+ if (fields.time) {
26
+ log.time = fields.time;
27
+ }
28
+ if (fields.body !== undefined) {
29
+ log.body = fields.body;
30
+ }
31
+ if (fields.traceId !== undefined) {
32
+ log.traceId = fields.traceId;
33
+ }
34
+ if (fields.spanId !== undefined) {
35
+ log.spanId = fields.spanId;
36
+ }
37
+ if (fields.severityText !== undefined) {
38
+ log.severityText = fields.severityText as unknown as Log["severityText"];
39
+ }
40
+ if (fields.attributes !== undefined) {
41
+ log.attributes = fields.attributes;
42
+ }
43
+ return log;
44
+ }
45
+
46
+ describe("exportLogsToCSV", () => {
47
+ test("emits a header row of human-readable labels", () => {
48
+ const csv: string = exportLogsToCSV([], ["time", "message", "traceId"]);
49
+ expect(csv).toBe("Time,Message,Trace ID");
50
+ });
51
+
52
+ test("serializes body/traceId/spanId fields into a row", () => {
53
+ const log: Log = makeLog({
54
+ body: "hello world",
55
+ traceId: "trace-1",
56
+ spanId: "span-1",
57
+ });
58
+
59
+ const csv: string = exportLogsToCSV(
60
+ [log],
61
+ ["message", "traceId", "spanId"],
62
+ );
63
+ const [, row] = csv.split("\n");
64
+ expect(row).toBe("hello world,trace-1,span-1");
65
+ });
66
+
67
+ test("quotes and escapes fields containing commas and quotes", () => {
68
+ const log: Log = makeLog({ body: 'a, b "c"' });
69
+ const csv: string = exportLogsToCSV([log], ["message"]);
70
+ // Message,\n"a, b ""c"""
71
+ expect(csv.split("\n")[1]).toBe('"a, b ""c"""');
72
+ });
73
+
74
+ test("quotes fields containing newlines", () => {
75
+ const log: Log = makeLog({ body: "line1\nline2" });
76
+ const csv: string = exportLogsToCSV([log], ["message"]);
77
+ // The whole field (including the embedded newline) is wrapped in quotes.
78
+ expect(csv).toBe('Message\n"line1\nline2"');
79
+ });
80
+
81
+ test("renders an ISO timestamp for the time column", () => {
82
+ const log: Log = makeLog({ time: new Date("2026-07-25T10:20:30.000Z") });
83
+ const csv: string = exportLogsToCSV([log], ["time"]);
84
+ expect(csv.split("\n")[1]).toBe("2026-07-25T10:20:30.000Z");
85
+ });
86
+
87
+ test("empty value for a missing scalar field", () => {
88
+ const log: Log = makeLog({ body: "x" });
89
+ const csv: string = exportLogsToCSV([log], ["traceId"]);
90
+ expect(csv.split("\n")[1]).toBe("");
91
+ });
92
+
93
+ test("reads dynamic attribute columns via the attribute: prefix", () => {
94
+ const log: Log = makeLog({
95
+ attributes: { "http.method": "GET", nested: { a: 1 } },
96
+ });
97
+
98
+ const csv: string = exportLogsToCSV(
99
+ [log],
100
+ ["attribute:http.method", "attribute:nested"],
101
+ );
102
+ const row: string = csv.split("\n")[1]!;
103
+ // nested object is JSON-stringified, which contains a comma -> quoted.
104
+ expect(row).toContain("GET");
105
+ expect(row).toContain('"{""a"":1}"');
106
+ });
107
+
108
+ test("attribute column is empty when the key is absent", () => {
109
+ const log: Log = makeLog({ attributes: { present: "1" } });
110
+ const csv: string = exportLogsToCSV([log], ["attribute:missing"]);
111
+ expect(csv.split("\n")[1]).toBe("");
112
+ });
113
+
114
+ test("unknown column id yields an empty cell and echoes the id as label", () => {
115
+ const log: Log = makeLog({ body: "x" });
116
+ const csv: string = exportLogsToCSV([log], ["totally-unknown"]);
117
+ expect(csv.split("\n")[0]).toBe("totally-unknown");
118
+ expect(csv.split("\n")[1]).toBe("");
119
+ });
120
+ });
121
+
122
+ describe("exportLogsToJSON", () => {
123
+ test("produces a pretty-printed array of log objects", () => {
124
+ const log: Log = makeLog({
125
+ time: new Date("2026-07-25T10:20:30.000Z"),
126
+ body: "hello",
127
+ traceId: "t1",
128
+ spanId: "s1",
129
+ attributes: { k: "v" },
130
+ });
131
+
132
+ const json: string = exportLogsToJSON([log]);
133
+ const parsed: Array<Record<string, unknown>> = JSON.parse(json);
134
+
135
+ expect(parsed).toHaveLength(1);
136
+ expect(parsed[0]!["time"]).toBe("2026-07-25T10:20:30.000Z");
137
+ expect(parsed[0]!["body"]).toBe("hello");
138
+ expect(parsed[0]!["traceId"]).toBe("t1");
139
+ expect(parsed[0]!["spanId"]).toBe("s1");
140
+ expect(parsed[0]!["attributes"]).toEqual({ k: "v" });
141
+ });
142
+
143
+ test("null fields for a sparse log, empty attributes object default", () => {
144
+ const log: Log = makeLog({ body: "only body" });
145
+ const parsed: Array<Record<string, unknown>> = JSON.parse(
146
+ exportLogsToJSON([log]),
147
+ );
148
+
149
+ expect(parsed[0]!["time"]).toBeNull();
150
+ expect(parsed[0]!["traceId"]).toBeNull();
151
+ expect(parsed[0]!["spanId"]).toBeNull();
152
+ expect(parsed[0]!["attributes"]).toEqual({});
153
+ expect(parsed[0]!["body"]).toBe("only body");
154
+ });
155
+
156
+ test("serializes an empty list to an empty JSON array", () => {
157
+ expect(exportLogsToJSON([])).toBe("[]");
158
+ });
159
+ });
@@ -0,0 +1,183 @@
1
+ import Navigation from "../../../UI/Utils/Navigation";
2
+ import {
3
+ afterEach,
4
+ beforeEach,
5
+ describe,
6
+ expect,
7
+ jest,
8
+ test,
9
+ } from "@jest/globals";
10
+
11
+ /*
12
+ * `Navigation.setQueryString` is the single write path for every piece of URL
13
+ * state in the app (table filters, facets, sort/pagination, the telemetry
14
+ * explorers). Its exact semantics are load-bearing:
15
+ *
16
+ * - it must MERGE, so one component writing its params never deletes another
17
+ * component's params from the same route;
18
+ * - it must use `replaceState`, so dragging a filter around doesn't bury the
19
+ * "back to the list" entry under a hundred history entries;
20
+ * - it must pass the CURRENT `history.state` through, because that object is
21
+ * react-router's `{usr, key, idx}` bookkeeping — replacing it with `null`
22
+ * corrupts the router's history index;
23
+ * - and it must leave the pathname and hash alone.
24
+ */
25
+
26
+ type SetUrlFunction = (url: string) => void;
27
+
28
+ const setUrl: SetUrlFunction = (url: string): void => {
29
+ window.history.replaceState(window.history.state, "", url);
30
+ };
31
+
32
+ describe("Navigation URL query string helpers", () => {
33
+ beforeEach(() => {
34
+ setUrl("/dashboard/monitors");
35
+ });
36
+
37
+ afterEach(() => {
38
+ jest.restoreAllMocks();
39
+ });
40
+
41
+ describe("getQueryString", () => {
42
+ test("returns the raw search string including the leading ?", () => {
43
+ setUrl("/dashboard/monitors?a=1&b=2");
44
+
45
+ expect(Navigation.getQueryString()).toBe("?a=1&b=2");
46
+ });
47
+
48
+ test("returns an empty string when there is no query", () => {
49
+ expect(Navigation.getQueryString()).toBe("");
50
+ });
51
+ });
52
+
53
+ describe("getQueryStringByName", () => {
54
+ test("reads a param and percent-decodes it", () => {
55
+ setUrl(`/dashboard/monitors?q=${encodeURIComponent('{"a":"b c"}')}`);
56
+
57
+ expect(Navigation.getQueryStringByName("q")).toBe('{"a":"b c"}');
58
+ });
59
+
60
+ test("returns null for a missing param", () => {
61
+ setUrl("/dashboard/monitors?other=1");
62
+
63
+ expect(Navigation.getQueryStringByName("q")).toBeNull();
64
+ });
65
+
66
+ test("returns null for a present-but-empty param", () => {
67
+ setUrl("/dashboard/monitors?q=");
68
+
69
+ expect(Navigation.getQueryStringByName("q")).toBeNull();
70
+ });
71
+ });
72
+
73
+ describe("setQueryString", () => {
74
+ test("adds a param without touching the ones already there", () => {
75
+ setUrl("/dashboard/monitors?existing=keepme");
76
+
77
+ Navigation.setQueryString({ added: "value" });
78
+
79
+ expect(Navigation.getQueryStringByName("existing")).toBe("keepme");
80
+ expect(Navigation.getQueryStringByName("added")).toBe("value");
81
+ });
82
+
83
+ test("overwrites only the named param", () => {
84
+ setUrl("/dashboard/monitors?a=1&b=2");
85
+
86
+ Navigation.setQueryString({ a: "9" });
87
+
88
+ expect(Navigation.getQueryStringByName("a")).toBe("9");
89
+ expect(Navigation.getQueryStringByName("b")).toBe("2");
90
+ });
91
+
92
+ test("deletes a param when the value is null", () => {
93
+ setUrl("/dashboard/monitors?a=1&b=2");
94
+
95
+ Navigation.setQueryString({ a: null });
96
+
97
+ expect(Navigation.getQueryStringByName("a")).toBeNull();
98
+ expect(Navigation.getQueryStringByName("b")).toBe("2");
99
+ });
100
+
101
+ test("deletes a param when the value is an empty string", () => {
102
+ setUrl("/dashboard/monitors?a=1");
103
+
104
+ Navigation.setQueryString({ a: "" });
105
+
106
+ expect(Navigation.getQueryStringByName("a")).toBeNull();
107
+ });
108
+
109
+ test("applies several params in one call", () => {
110
+ setUrl("/dashboard/monitors?keep=1&drop=2");
111
+
112
+ Navigation.setQueryString({ drop: null, one: "1", two: "2" });
113
+
114
+ expect(Navigation.getQueryStringByName("keep")).toBe("1");
115
+ expect(Navigation.getQueryStringByName("drop")).toBeNull();
116
+ expect(Navigation.getQueryStringByName("one")).toBe("1");
117
+ expect(Navigation.getQueryStringByName("two")).toBe("2");
118
+ });
119
+
120
+ test("leaves the pathname and hash intact", () => {
121
+ setUrl("/dashboard/monitors/abc#section-two");
122
+
123
+ Navigation.setQueryString({ a: "1" });
124
+
125
+ expect(window.location.pathname).toBe("/dashboard/monitors/abc");
126
+ expect(window.location.hash).toBe("#section-two");
127
+ expect(Navigation.getQueryStringByName("a")).toBe("1");
128
+ });
129
+
130
+ test("drops the '?' entirely when the last param is removed", () => {
131
+ setUrl("/dashboard/monitors?only=1");
132
+
133
+ Navigation.setQueryString({ only: null });
134
+
135
+ expect(window.location.search).toBe("");
136
+ });
137
+
138
+ test("round-trips a value containing URL-significant characters", () => {
139
+ const value: string = '{"name":{"_type":"Search","value":"a&b=c d"}}';
140
+
141
+ Navigation.setQueryString({ q: value });
142
+
143
+ expect(Navigation.getQueryStringByName("q")).toBe(value);
144
+ });
145
+
146
+ test("replaces the current history entry instead of pushing a new one", () => {
147
+ const lengthBefore: number = window.history.length;
148
+
149
+ Navigation.setQueryString({ a: "1" });
150
+ Navigation.setQueryString({ a: "2" });
151
+ Navigation.setQueryString({ a: "3" });
152
+
153
+ expect(window.history.length).toBe(lengthBefore);
154
+ });
155
+
156
+ test("preserves history.state so react-router's bookkeeping survives", () => {
157
+ const routerState: { usr: null; key: string; idx: number } = {
158
+ usr: null,
159
+ key: "abc123",
160
+ idx: 4,
161
+ };
162
+ window.history.replaceState(routerState, "", "/dashboard/monitors");
163
+
164
+ Navigation.setQueryString({ a: "1" });
165
+
166
+ expect(window.history.state).toEqual(routerState);
167
+ });
168
+
169
+ test("swallows the SecurityError Safari throws when replaceState is called too often", () => {
170
+ const replaceState: ReturnType<typeof jest.spyOn> = jest
171
+ .spyOn(window.history, "replaceState")
172
+ .mockImplementation(() => {
173
+ throw new Error("SecurityError: too many calls to replaceState");
174
+ });
175
+
176
+ expect(() => {
177
+ Navigation.setQueryString({ a: "1" });
178
+ }).not.toThrow();
179
+
180
+ expect(replaceState).toHaveBeenCalled();
181
+ });
182
+ });
183
+ });