@oneuptime/common 11.6.1 → 11.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (420) hide show
  1. package/Models/AnalyticsModels/Index.ts +4 -0
  2. package/Models/AnalyticsModels/KubernetesCostAllocation.ts +842 -0
  3. package/Models/AnalyticsModels/NetworkFlow.ts +54 -0
  4. package/Models/AnalyticsModels/SloHistory.ts +243 -0
  5. package/Models/DatabaseModels/Index.ts +20 -0
  6. package/Models/DatabaseModels/NetworkDevice.ts +453 -6
  7. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +7 -6
  8. package/Models/DatabaseModels/NetworkEndpoint.ts +753 -0
  9. package/Models/DatabaseModels/NetworkSite.ts +1155 -0
  10. package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +517 -0
  11. package/Models/DatabaseModels/NetworkSiteLink.ts +611 -0
  12. package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +520 -0
  13. package/Models/DatabaseModels/NetworkSiteType.ts +499 -0
  14. package/Models/DatabaseModels/ServiceLevelObjective.ts +1115 -0
  15. package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +762 -0
  16. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +444 -0
  17. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +443 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.ts +359 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.ts +48 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.ts +65 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.ts +88 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.ts +391 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1785066759532-MigrationName.ts +30 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
  25. package/Server/Services/AnalyticsDatabaseService.ts +25 -9
  26. package/Server/Services/Index.ts +24 -0
  27. package/Server/Services/KubernetesCostAllocationService.ts +14 -0
  28. package/Server/Services/MetricService.ts +21 -2
  29. package/Server/Services/MonitorService.ts +22 -0
  30. package/Server/Services/NetworkDeviceService.ts +438 -2
  31. package/Server/Services/NetworkEndpointService.ts +414 -0
  32. package/Server/Services/NetworkSiteAssignmentRuleService.ts +98 -0
  33. package/Server/Services/NetworkSiteLinkService.ts +10 -0
  34. package/Server/Services/NetworkSiteService.ts +1254 -0
  35. package/Server/Services/NetworkSiteStatusTimelineService.ts +10 -0
  36. package/Server/Services/NetworkSiteTypeService.ts +10 -0
  37. package/Server/Services/ProjectService.ts +122 -2
  38. package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +457 -0
  39. package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +10 -0
  40. package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +10 -0
  41. package/Server/Services/ServiceLevelObjectiveService.ts +685 -0
  42. package/Server/Services/SloHistoryService.ts +101 -0
  43. package/Server/Services/UserNotificationSettingService.ts +37 -0
  44. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +9 -0
  45. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +15 -0
  46. package/Server/Utils/AnalyticsDatabase/Statement.ts +39 -3
  47. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +87 -48
  48. package/Server/Utils/Memory.ts +9 -1
  49. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +190 -12
  50. package/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  51. package/Server/Utils/Monitor/DnsResolutionCache.ts +129 -0
  52. package/Server/Utils/Monitor/MonitorResource.ts +4 -30
  53. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +214 -39
  54. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +343 -0
  55. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +251 -0
  56. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +176 -142
  57. package/Server/Utils/Monitor/OuiLookupUtil.ts +49 -0
  58. package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +17 -13
  59. package/Server/Utils/WhatsAppTemplateUtil.ts +7 -3
  60. package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +135 -0
  61. package/Tests/Models/NetworkSiteHierarchy.test.ts +134 -0
  62. package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +239 -0
  63. package/Tests/Server/Services/KubernetesCostAllocationAggregate.test.ts +338 -0
  64. package/Tests/Server/Services/MetricServiceAggregate.test.ts +142 -0
  65. package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +484 -0
  66. package/Tests/Server/Services/NetworkEndpointServiceUpsert.test.ts +686 -0
  67. package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +185 -0
  68. package/Tests/Server/Services/NetworkSiteService.test.ts +1354 -0
  69. package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +1313 -0
  70. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +1988 -0
  71. package/Tests/Server/Utils/AnalyticsDatabase/Statement.test.ts +22 -0
  72. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +404 -0
  73. package/Tests/Server/Utils/Encryption.test.ts +70 -0
  74. package/Tests/Server/Utils/FileAttachmentMarkdownUtil.test.ts +225 -0
  75. package/Tests/Server/Utils/JsonWebToken.test.ts +175 -0
  76. package/Tests/Server/Utils/LocalFile.test.ts +258 -0
  77. package/Tests/Server/Utils/Memory.test.ts +213 -0
  78. package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +30 -0
  79. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +385 -0
  80. package/Tests/Server/Utils/Monitor/DnsResolutionCache.test.ts +194 -0
  81. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +155 -0
  82. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +600 -0
  83. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +151 -124
  84. package/Tests/Server/Utils/Monitor/SnmpInterfaceRateUtil.test.ts +496 -0
  85. package/Tests/Server/Utils/MonitorCriteriaDataExtractor.test.ts +175 -0
  86. package/Tests/Server/Utils/MonitorCriteriaMessageFormatter.test.ts +282 -0
  87. package/Tests/Server/Utils/OuiLookupUtil.test.ts +59 -0
  88. package/Tests/Server/Utils/SeriesResourceLabels.test.ts +117 -0
  89. package/Tests/Server/Utils/StackTraceParser.test.ts +370 -0
  90. package/Tests/Server/Utils/Stream.test.ts +87 -0
  91. package/Tests/Server/Utils/ValidateGlobalProviderProjectTeams.test.ts +221 -0
  92. package/Tests/Server/Utils/WhatsAppTemplateUtil.test.ts +199 -0
  93. package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +33 -0
  94. package/Tests/Types/Email.test.ts +198 -0
  95. package/Tests/Types/Kubernetes/KubernetesObjectParser.test.ts +177 -0
  96. package/Tests/Types/Log/LogQueryToFilter.test.ts +111 -0
  97. package/Tests/Types/Monitor/MonitorCriteria.test.ts +155 -0
  98. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +465 -0
  99. package/Tests/Types/Monitor/MonitorStep.test.ts +183 -0
  100. package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +141 -1
  101. package/Tests/Types/Monitor/MonitorSteps.test.ts +183 -0
  102. package/Tests/Types/Monitor/MonitorType.test.ts +59 -1
  103. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +97 -0
  104. package/Tests/Types/Monitor/SnmpEndpointDiscovery.test.ts +151 -0
  105. package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +110 -6
  106. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +129 -0
  107. package/Tests/Types/SerializableObjectDictionary.test.ts +166 -0
  108. package/Tests/Types/Time/RangeStartAndEndDateTime.test.ts +98 -0
  109. package/Tests/Types/WebsiteRequest.test.ts +230 -0
  110. package/Tests/UI/Components/EntityFilterRoundTrip.test.tsx +103 -0
  111. package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +612 -0
  112. package/Tests/UI/Components/ModelTable/FilterDataToQuery.test.ts +275 -0
  113. package/Tests/UI/Utils/LogExport.test.ts +159 -0
  114. package/Tests/UI/Utils/Navigation.test.ts +183 -0
  115. package/Tests/UI/Utils/TableFilterUrlState.test.ts +539 -0
  116. package/Tests/UI/Utils/TableViewUrlState.test.ts +272 -0
  117. package/Tests/Utils/Base64.test.ts +51 -0
  118. package/Tests/Utils/Boolean.test.ts +76 -0
  119. package/Tests/Utils/Crypto.test.ts +48 -0
  120. package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +259 -0
  121. package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +162 -0
  122. package/Tests/Utils/Enum.test.ts +54 -0
  123. package/Tests/Utils/IpCanonicalUtil.test.ts +85 -0
  124. package/Tests/Utils/Memory.test.ts +44 -0
  125. package/Tests/Utils/Metrics/MetricSeriesFingerprint.test.ts +160 -0
  126. package/Tests/Utils/Monitor/EndpointAttachmentUtil.test.ts +836 -0
  127. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +218 -0
  128. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +447 -0
  129. package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +440 -0
  130. package/Tests/Utils/NetworkSite/MaterializedPathUtil.test.ts +205 -0
  131. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +221 -0
  132. package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +283 -0
  133. package/Tests/Utils/ObjectUtil.test.ts +30 -0
  134. package/Tests/Utils/Slo/SloBurnRateRuleState.test.ts +124 -0
  135. package/Tests/Utils/Slo/SloDuration.test.ts +148 -0
  136. package/Tests/Utils/Slo/SloHealth.test.ts +334 -0
  137. package/Tests/Utils/Slo/SloStatusColor.test.ts +89 -0
  138. package/Tests/Utils/Slo/SloUtil.test.ts +1980 -0
  139. package/Tests/Utils/Slo/SloWidgetFormat.test.ts +605 -0
  140. package/Tests/Utils/TechStack.test.ts +50 -0
  141. package/Tests/Utils/Traces/CriticalPath.test.ts +178 -0
  142. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +10 -0
  143. package/Types/BaseDatabase/EqualTo.ts +9 -1
  144. package/Types/BaseDatabase/EqualToOrNull.ts +9 -1
  145. package/Types/BaseDatabase/NotEqual.ts +9 -1
  146. package/Types/Dashboard/DashboardComponentType.ts +1 -0
  147. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
  148. package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +42 -0
  149. package/Types/Dashboard/DashboardTemplates.ts +214 -0
  150. package/Types/Email/EmailTemplateType.ts +2 -0
  151. package/Types/Kubernetes/KubernetesCostIngest.ts +79 -0
  152. package/Types/Monitor/CriteriaFilter.ts +9 -0
  153. package/Types/Monitor/MonitorStep.ts +5 -8
  154. package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +27 -5
  155. package/Types/Monitor/MonitorType.ts +15 -5
  156. package/Types/Monitor/SnmpMonitor/ArpEntry.ts +14 -0
  157. package/Types/Monitor/SnmpMonitor/FdbEntry.ts +18 -0
  158. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +10 -3
  159. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -5
  160. package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +12 -0
  161. package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +231 -3
  162. package/Types/NetworkSite/DefaultNetworkSiteType.ts +20 -0
  163. package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
  164. package/Types/Permission.ts +449 -0
  165. package/Types/ServiceLevelObjective/SliType.ts +6 -0
  166. package/Types/ServiceLevelObjective/SloMultiMonitorMode.ts +6 -0
  167. package/Types/ServiceLevelObjective/SloStatus.ts +9 -0
  168. package/Types/ServiceLevelObjective/SloWindowType.ts +6 -0
  169. package/Types/Telemetry/ServiceType.ts +1 -0
  170. package/UI/Components/Filters/EntityFilter.tsx +16 -0
  171. package/UI/Components/Filters/FilterViewer.tsx +22 -5
  172. package/UI/Components/List/List.tsx +8 -0
  173. package/UI/Components/ModelTable/BaseModelTable.tsx +309 -106
  174. package/UI/Components/ModelTable/FilterDataToQuery.ts +172 -0
  175. package/UI/Components/Navbar/NavBar.tsx +16 -2
  176. package/UI/Components/Navbar/NavBarMenuModal.tsx +3 -3
  177. package/UI/Utils/Navigation.ts +10 -0
  178. package/UI/Utils/TableFilterUrlState.ts +204 -17
  179. package/UI/Utils/TableViewUrlState.ts +165 -0
  180. package/Utils/Dashboard/Components/DashboardSloComponent.ts +114 -0
  181. package/Utils/Dashboard/Components/Index.ts +7 -0
  182. package/Utils/IpCanonicalUtil.ts +134 -0
  183. package/Utils/Monitor/EndpointAttachmentUtil.ts +508 -0
  184. package/Utils/Monitor/NetworkTopologyUtil.ts +157 -5
  185. package/Utils/NetworkSite/CidrMatchUtil.ts +296 -0
  186. package/Utils/NetworkSite/MaterializedPathUtil.ts +115 -0
  187. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +97 -0
  188. package/Utils/NetworkSite/SiteUptimeUtil.ts +111 -0
  189. package/Utils/Slo/SloBurnRateRuleState.ts +91 -0
  190. package/Utils/Slo/SloDuration.ts +165 -0
  191. package/Utils/Slo/SloEvaluation.ts +22 -0
  192. package/Utils/Slo/SloHealth.ts +302 -0
  193. package/Utils/Slo/SloStatusColor.ts +54 -0
  194. package/Utils/Slo/SloUtil.ts +637 -0
  195. package/Utils/Slo/SloWidgetFormat.ts +383 -0
  196. package/build/dist/Models/AnalyticsModels/Index.js +4 -0
  197. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  198. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +713 -0
  199. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -0
  200. package/build/dist/Models/AnalyticsModels/NetworkFlow.js +44 -0
  201. package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
  202. package/build/dist/Models/AnalyticsModels/SloHistory.js +218 -0
  203. package/build/dist/Models/AnalyticsModels/SloHistory.js.map +1 -0
  204. package/build/dist/Models/DatabaseModels/Index.js +20 -0
  205. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  206. package/build/dist/Models/DatabaseModels/NetworkDevice.js +458 -6
  207. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  208. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +0 -6
  209. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  210. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js +779 -0
  211. package/build/dist/Models/DatabaseModels/NetworkEndpoint.js.map +1 -0
  212. package/build/dist/Models/DatabaseModels/NetworkSite.js +1180 -0
  213. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -0
  214. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +534 -0
  215. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -0
  216. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js +629 -0
  217. package/build/dist/Models/DatabaseModels/NetworkSiteLink.js.map +1 -0
  218. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +538 -0
  219. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -0
  220. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +522 -0
  221. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -0
  222. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +1134 -0
  223. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -0
  224. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +769 -0
  225. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -0
  226. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +460 -0
  227. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -0
  228. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +459 -0
  229. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -0
  230. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js +130 -0
  231. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js.map +1 -0
  232. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js +31 -0
  233. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js.map +1 -0
  234. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js +36 -0
  235. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js.map +1 -0
  236. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js +49 -0
  237. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js.map +1 -0
  238. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js +140 -0
  239. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js.map +1 -0
  240. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785066759532-MigrationName.js +21 -0
  241. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785066759532-MigrationName.js.map +1 -0
  242. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
  243. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  244. package/build/dist/Server/Services/AnalyticsDatabaseService.js +23 -6
  245. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  246. package/build/dist/Server/Services/Index.js +24 -0
  247. package/build/dist/Server/Services/Index.js.map +1 -1
  248. package/build/dist/Server/Services/KubernetesCostAllocationService.js +12 -0
  249. package/build/dist/Server/Services/KubernetesCostAllocationService.js.map +1 -0
  250. package/build/dist/Server/Services/MetricService.js +21 -3
  251. package/build/dist/Server/Services/MetricService.js.map +1 -1
  252. package/build/dist/Server/Services/MonitorService.js +19 -0
  253. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  254. package/build/dist/Server/Services/NetworkDeviceService.js +351 -1
  255. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  256. package/build/dist/Server/Services/NetworkEndpointService.js +319 -0
  257. package/build/dist/Server/Services/NetworkEndpointService.js.map +1 -0
  258. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +90 -0
  259. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -0
  260. package/build/dist/Server/Services/NetworkSiteLinkService.js +9 -0
  261. package/build/dist/Server/Services/NetworkSiteLinkService.js.map +1 -0
  262. package/build/dist/Server/Services/NetworkSiteService.js +1038 -0
  263. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -0
  264. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js +9 -0
  265. package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js.map +1 -0
  266. package/build/dist/Server/Services/NetworkSiteTypeService.js +9 -0
  267. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -0
  268. package/build/dist/Server/Services/ProjectService.js +98 -2
  269. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  270. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +358 -0
  271. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -0
  272. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +9 -0
  273. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -0
  274. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +9 -0
  275. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -0
  276. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +588 -0
  277. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -0
  278. package/build/dist/Server/Services/SloHistoryService.js +77 -0
  279. package/build/dist/Server/Services/SloHistoryService.js.map +1 -0
  280. package/build/dist/Server/Services/UserNotificationSettingService.js +20 -0
  281. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  282. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +9 -0
  283. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  284. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +15 -0
  285. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  286. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +31 -0
  287. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  288. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +76 -48
  289. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  290. package/build/dist/Server/Utils/Memory.js +9 -1
  291. package/build/dist/Server/Utils/Memory.js.map +1 -1
  292. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +132 -10
  293. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  294. package/build/dist/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
  295. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js +77 -0
  296. package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js.map +1 -0
  297. package/build/dist/Server/Utils/Monitor/MonitorResource.js +21 -41
  298. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  299. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +152 -40
  300. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  301. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +262 -0
  302. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -0
  303. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +201 -0
  304. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -0
  305. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +152 -120
  306. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  307. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js +44 -0
  308. package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js.map +1 -0
  309. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +10 -10
  310. package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -1
  311. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +5 -0
  312. package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
  313. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +10 -0
  314. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  315. package/build/dist/Types/BaseDatabase/EqualTo.js +9 -1
  316. package/build/dist/Types/BaseDatabase/EqualTo.js.map +1 -1
  317. package/build/dist/Types/BaseDatabase/EqualToOrNull.js +9 -1
  318. package/build/dist/Types/BaseDatabase/EqualToOrNull.js.map +1 -1
  319. package/build/dist/Types/BaseDatabase/NotEqual.js +9 -1
  320. package/build/dist/Types/BaseDatabase/NotEqual.js.map +1 -1
  321. package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
  322. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  323. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
  324. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  325. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js +23 -0
  326. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js.map +1 -0
  327. package/build/dist/Types/Dashboard/DashboardTemplates.js +205 -0
  328. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  329. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  330. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  331. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js +21 -0
  332. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -0
  333. package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
  334. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  335. package/build/dist/Types/Monitor/MonitorStep.js +5 -5
  336. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  337. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +8 -0
  338. package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -1
  339. package/build/dist/Types/Monitor/MonitorType.js +15 -5
  340. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  341. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js +2 -0
  342. package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js.map +1 -0
  343. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js +2 -0
  344. package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js.map +1 -0
  345. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +9 -3
  346. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  347. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +217 -3
  348. package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
  349. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js +21 -0
  350. package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js.map +1 -0
  351. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
  352. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  353. package/build/dist/Types/Permission.js +409 -0
  354. package/build/dist/Types/Permission.js.map +1 -1
  355. package/build/dist/Types/ServiceLevelObjective/SliType.js +7 -0
  356. package/build/dist/Types/ServiceLevelObjective/SliType.js.map +1 -0
  357. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js +7 -0
  358. package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js.map +1 -0
  359. package/build/dist/Types/ServiceLevelObjective/SloStatus.js +10 -0
  360. package/build/dist/Types/ServiceLevelObjective/SloStatus.js.map +1 -0
  361. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js +7 -0
  362. package/build/dist/Types/ServiceLevelObjective/SloWindowType.js.map +1 -0
  363. package/build/dist/Types/Telemetry/ServiceType.js +1 -0
  364. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  365. package/build/dist/UI/Components/Filters/EntityFilter.js +15 -0
  366. package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
  367. package/build/dist/UI/Components/Filters/FilterViewer.js +19 -4
  368. package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
  369. package/build/dist/UI/Components/List/List.js +1 -1
  370. package/build/dist/UI/Components/List/List.js.map +1 -1
  371. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +235 -89
  372. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  373. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js +96 -0
  374. package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js.map +1 -0
  375. package/build/dist/UI/Components/Navbar/NavBar.js +14 -2
  376. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  377. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +3 -2
  378. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  379. package/build/dist/UI/Utils/Navigation.js +9 -0
  380. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  381. package/build/dist/UI/Utils/TableFilterUrlState.js +159 -15
  382. package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
  383. package/build/dist/UI/Utils/TableViewUrlState.js +103 -0
  384. package/build/dist/UI/Utils/TableViewUrlState.js.map +1 -0
  385. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +93 -0
  386. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -0
  387. package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
  388. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  389. package/build/dist/Utils/IpCanonicalUtil.js +110 -0
  390. package/build/dist/Utils/IpCanonicalUtil.js.map +1 -0
  391. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js +311 -0
  392. package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js.map +1 -0
  393. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +98 -5
  394. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  395. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +222 -0
  396. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -0
  397. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js +89 -0
  398. package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js.map +1 -0
  399. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +60 -0
  400. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -0
  401. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +76 -0
  402. package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -0
  403. package/build/dist/Utils/Slo/SloBurnRateRuleState.js +35 -0
  404. package/build/dist/Utils/Slo/SloBurnRateRuleState.js.map +1 -0
  405. package/build/dist/Utils/Slo/SloDuration.js +87 -0
  406. package/build/dist/Utils/Slo/SloDuration.js.map +1 -0
  407. package/build/dist/Utils/Slo/SloEvaluation.js +21 -0
  408. package/build/dist/Utils/Slo/SloEvaluation.js.map +1 -0
  409. package/build/dist/Utils/Slo/SloHealth.js +179 -0
  410. package/build/dist/Utils/Slo/SloHealth.js.map +1 -0
  411. package/build/dist/Utils/Slo/SloStatusColor.js +18 -0
  412. package/build/dist/Utils/Slo/SloStatusColor.js.map +1 -0
  413. package/build/dist/Utils/Slo/SloUtil.js +393 -0
  414. package/build/dist/Utils/Slo/SloUtil.js.map +1 -0
  415. package/build/dist/Utils/Slo/SloWidgetFormat.js +174 -0
  416. package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -0
  417. package/package.json +2 -2
  418. package/Types/Dashboard/DashboardComponents/Index.ts +0 -7
  419. package/build/dist/Types/Dashboard/DashboardComponents/Index.js +0 -8
  420. package/build/dist/Types/Dashboard/DashboardComponents/Index.js.map +0 -1
@@ -0,0 +1,172 @@
1
+ import Filter from "../ModelFilter/Filter";
2
+ import FilterData from "../Filters/Types/FilterData";
3
+ import FieldType from "../Types/FieldType";
4
+ import AnalyticsBaseModel from "../../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
5
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
6
+ import Includes from "../../../Types/BaseDatabase/Includes";
7
+ import InBetween from "../../../Types/BaseDatabase/InBetween";
8
+ import Query from "../../../Types/BaseDatabase/Query";
9
+ import QueryOperator from "../../../Types/BaseDatabase/QueryOperator";
10
+ import Search from "../../../Types/BaseDatabase/Search";
11
+ import Typeof from "../../../Types/Typeof";
12
+
13
+ /**
14
+ * Translate the filter popup's selections into the database query the table
15
+ * fetches with.
16
+ *
17
+ * Lives outside `BaseModelTable` on purpose: the table needs to derive the
18
+ * query *synchronously during its first render* when filters are restored from
19
+ * the URL (otherwise the first fetch would go out unfiltered and be
20
+ * immediately superseded), and a pure function is the only way to do that
21
+ * without an effect.
22
+ */
23
+ export type GetFilterKeysFunction = <
24
+ TBaseModel extends BaseModel | AnalyticsBaseModel,
25
+ >(
26
+ filters: Array<Filter<TBaseModel>>,
27
+ ) => Array<string>;
28
+
29
+ /**
30
+ * The model fields this table actually exposes a filter for.
31
+ */
32
+ export const getFilterKeys: GetFilterKeysFunction = <
33
+ TBaseModel extends BaseModel | AnalyticsBaseModel,
34
+ >(
35
+ filters: Array<Filter<TBaseModel>>,
36
+ ): Array<string> => {
37
+ const keys: Array<string> = [];
38
+
39
+ for (const filter of filters || []) {
40
+ const key: string | undefined = filter.field
41
+ ? Object.keys(filter.field)[0]
42
+ : undefined;
43
+
44
+ if (key) {
45
+ keys.push(key);
46
+ }
47
+ }
48
+
49
+ return keys;
50
+ };
51
+
52
+ export type SanitizeFilterDataFunction = <
53
+ TBaseModel extends BaseModel | AnalyticsBaseModel,
54
+ >(data: {
55
+ filterData: FilterData<TBaseModel>;
56
+ filters: Array<Filter<TBaseModel>>;
57
+ }) => FilterData<TBaseModel>;
58
+
59
+ /**
60
+ * Drop any key that this table does not expose as a filter.
61
+ *
62
+ * The filter snapshot arrives from the URL, which anyone can edit, and the
63
+ * result is spread into the outgoing list query *after* the caller's own
64
+ * scoping query. Without this, a hand-crafted link could add a constraint on a
65
+ * field the table never offered — or overwrite the page's own scoping (say the
66
+ * `projectId` on a nested list) — just by naming it in the query string.
67
+ *
68
+ * Restricting to declared filter keys keeps a shared link to exactly what the
69
+ * filter UI could have produced.
70
+ */
71
+ const sanitizeFilterData: SanitizeFilterDataFunction = <
72
+ TBaseModel extends BaseModel | AnalyticsBaseModel,
73
+ >(data: {
74
+ filterData: FilterData<TBaseModel>;
75
+ filters: Array<Filter<TBaseModel>>;
76
+ }): FilterData<TBaseModel> => {
77
+ const allowedKeys: Array<string> = getFilterKeys<TBaseModel>(data.filters);
78
+ const sanitized: FilterData<TBaseModel> = {};
79
+
80
+ for (const key in data.filterData || {}) {
81
+ if (!allowedKeys.includes(key)) {
82
+ continue;
83
+ }
84
+
85
+ const value: unknown = (data.filterData as any)[key];
86
+
87
+ if (value === undefined || value === null) {
88
+ continue;
89
+ }
90
+
91
+ (sanitized as any)[key] = value;
92
+ }
93
+
94
+ return sanitized;
95
+ };
96
+
97
+ export { sanitizeFilterData };
98
+
99
+ export type BuildQueryFromFilterDataFunction = <
100
+ TBaseModel extends BaseModel | AnalyticsBaseModel,
101
+ >(data: {
102
+ filterData: FilterData<TBaseModel>;
103
+ filters: Array<Filter<TBaseModel>>;
104
+ }) => Query<TBaseModel>;
105
+
106
+ const buildQueryFromFilterData: BuildQueryFromFilterDataFunction = <
107
+ TBaseModel extends BaseModel | AnalyticsBaseModel,
108
+ >(data: {
109
+ filterData: FilterData<TBaseModel>;
110
+ filters: Array<Filter<TBaseModel>>;
111
+ }): Query<TBaseModel> => {
112
+ const filterData: FilterData<TBaseModel> = data.filterData || {};
113
+ const filters: Array<Filter<TBaseModel>> = data.filters || [];
114
+
115
+ const query: Query<TBaseModel> = {};
116
+
117
+ for (const key in filterData) {
118
+ const value: unknown = filterData[key];
119
+
120
+ if (value && typeof value === Typeof.String) {
121
+ query[key as keyof TBaseModel] = (value || "").toString();
122
+ }
123
+
124
+ if (typeof value === Typeof.Boolean) {
125
+ query[key as keyof TBaseModel] = Boolean(value);
126
+ }
127
+
128
+ if (typeof value === Typeof.Number) {
129
+ query[key as keyof TBaseModel] = value as any;
130
+ }
131
+
132
+ if (value instanceof Date) {
133
+ query[key as keyof TBaseModel] = value as any;
134
+ }
135
+
136
+ if (value instanceof Search) {
137
+ query[key as keyof TBaseModel] = value as any;
138
+ }
139
+
140
+ if (value instanceof InBetween) {
141
+ query[key as keyof TBaseModel] = value as any;
142
+ }
143
+
144
+ if (
145
+ filters.find((f: Filter<TBaseModel>) => {
146
+ return f.field && (f.field as any)[key];
147
+ })?.type === FieldType.JSON &&
148
+ typeof value === Typeof.Object
149
+ ) {
150
+ query[key as keyof TBaseModel] = value as any;
151
+ }
152
+
153
+ if (Array.isArray(value)) {
154
+ query[key as keyof TBaseModel] = new Includes(
155
+ value as Array<string>,
156
+ ) as any;
157
+ }
158
+
159
+ /*
160
+ * Pass any QueryOperator instance (IncludesAll, IncludesNone, StartsWith,
161
+ * EndsWith, NotContains, EqualTo, NotEqual, GreaterThan, LessThan,
162
+ * InBetween, IsNull, NotNull, ...) through to the query as-is.
163
+ */
164
+ if (value instanceof QueryOperator) {
165
+ query[key as keyof TBaseModel] = value as any;
166
+ }
167
+ }
168
+
169
+ return query;
170
+ };
171
+
172
+ export default buildQueryFromFilterData;
@@ -33,6 +33,21 @@ export interface MoreMenuItem {
33
33
  iconColor?: string; // Tailwind color name like "blue", "purple", "amber"
34
34
  category?: string; // Category for grouping items (e.g., "Essentials", "Observability")
35
35
  activeRoute?: Route | undefined; // Route to check for active state
36
+ additionalActiveRoutes?: Array<Route> | undefined; // Extra routes that also mark this item active
37
+ }
38
+
39
+ /*
40
+ * One menu item can own several route prefixes (e.g. a merged "Network" item
41
+ * spanning /network-devices and /network-sites) — check them all.
42
+ */
43
+ export function isMoreMenuItemActive(item: MoreMenuItem): boolean {
44
+ const routesToCheck: Array<Route> = [
45
+ item.activeRoute || item.route,
46
+ ...(item.additionalActiveRoutes || []),
47
+ ];
48
+ return routesToCheck.some((route: Route) => {
49
+ return Navigation.isStartWith(route);
50
+ });
36
51
  }
37
52
 
38
53
  export interface ComponentProps {
@@ -254,8 +269,7 @@ const Navbar: FunctionComponent<ComponentProps> = (
254
269
  // Find active item in more menu items (needed for breadcrumb)
255
270
  const activeMoreItem: MoreMenuItem | undefined = props.moreMenuItems?.find(
256
271
  (item: MoreMenuItem) => {
257
- const routeToCheck: Route = item.activeRoute || item.route;
258
- return Navigation.isStartWith(routeToCheck);
272
+ return isMoreMenuItemActive(item);
259
273
  },
260
274
  );
261
275
 
@@ -3,7 +3,7 @@ import Link from "../Link/Link";
3
3
  import Navigation from "../../Utils/Navigation";
4
4
  import IconProp from "../../../Types/Icon/IconProp";
5
5
  import URL from "../../../Types/API/URL";
6
- import type { MoreMenuItem } from "./NavBar";
6
+ import { isMoreMenuItemActive, type MoreMenuItem } from "./NavBar";
7
7
  import React, {
8
8
  FunctionComponent,
9
9
  ReactElement,
@@ -209,7 +209,7 @@ const NavBarMenuModal: FunctionComponent<ComponentProps> = (
209
209
  const resolved: MoreMenuItem[] = [];
210
210
  recentRoutes.forEach((route: string) => {
211
211
  const item: MoreMenuItem | undefined = itemByRoute.get(route);
212
- if (item && !Navigation.isStartWith(item.activeRoute || item.route)) {
212
+ if (item && !isMoreMenuItemActive(item)) {
213
213
  resolved.push(item);
214
214
  }
215
215
  });
@@ -269,7 +269,7 @@ const NavBarMenuModal: FunctionComponent<ComponentProps> = (
269
269
  // Index of the product matching the current page (the "you are here" item).
270
270
  const currentFlatIndex: number = useMemo(() => {
271
271
  return flatItems.findIndex((item: MoreMenuItem) => {
272
- return Navigation.isStartWith(item.activeRoute || item.route);
272
+ return isMoreMenuItemActive(item);
273
273
  });
274
274
  }, [flatItems]);
275
275
 
@@ -52,6 +52,16 @@ abstract class Navigation {
52
52
  return pathes?.[0]?.route.path || "";
53
53
  }
54
54
 
55
+ /**
56
+ * The raw query string of the current URL, including the leading "?" when
57
+ * non-empty (i.e. exactly `window.location.search`). Reading it through
58
+ * Navigation keeps callers testable and consistent with
59
+ * {@link setQueryString}, which also works off `window.location`.
60
+ */
61
+ public static getQueryString(): string {
62
+ return window.location.search;
63
+ }
64
+
55
65
  public static getQueryStringByName(paramName: string): string | null {
56
66
  const urlSearchParams: URLSearchParams = new URLSearchParams(
57
67
  window.location.search,
@@ -1,28 +1,126 @@
1
1
  import Navigation from "./Navigation";
2
+ import Dictionary from "../../Types/Dictionary";
2
3
  import { JSONObject } from "../../Types/JSON";
3
4
  import JSONFunctions from "../../Types/JSONFunctions";
5
+ import { Logger } from "./Logger";
6
+ import { VoidFunction } from "../../Types/FunctionTypes";
4
7
 
5
- export type TableFilterUrlStateKind = "facets" | "filter";
8
+ /**
9
+ * The three independent slices of a table's view state. Each is stored under
10
+ * its own `<tableId>-<kind>` query param so a change to one never has to
11
+ * re-serialize the others.
12
+ *
13
+ * - `filter` — the classic column-filter popup selections (`FilterData`).
14
+ * - `facets` — the chip/facet bar selections (see `useResourceOwners`).
15
+ * - `view` — search text, label chips, sort and pagination.
16
+ */
17
+ export type TableFilterUrlStateKind = "facets" | "filter" | "view";
18
+
19
+ export const TableFilterUrlStateKinds: Array<TableFilterUrlStateKind> = [
20
+ "filter",
21
+ "facets",
22
+ "view",
23
+ ];
6
24
 
7
25
  /**
8
- * Persists a table's filter/facet selections in the URL query string so they:
26
+ * Persists a table's filter / facet / view selections in the URL query string
27
+ * so they:
9
28
  * - survive navigating to a detail page and clicking the browser "Back" button
10
29
  * (the list page remounts with the params still on the URL), and
11
30
  * - are shareable/bookmarkable (the URL fully describes the filtered view).
12
31
  *
13
32
  * The snapshot is run through {@link JSONFunctions} so OneUptime's typed query
14
33
  * values (Search, Includes, InBetween, ...) round-trip as real class instances
15
- * rather than plain objects. Params are namespaced by `tableId` so two tables on
16
- * the same route don't clobber each other.
34
+ * rather than plain objects. Params are namespaced by `tableId` so several
35
+ * tables on the same route each keep their own state.
17
36
  */
18
37
  export default class TableFilterUrlState {
19
- private static getParamName(
38
+ /**
39
+ * Upper bound on the whole query string we are willing to produce.
40
+ *
41
+ * nginx's default `large_client_header_buffers` gives ~8KB for the entire
42
+ * request line, and that budget is shared with the path and every other
43
+ * table on the page. We stay well under it: past this point the table keeps
44
+ * working from React state, it just stops mirroring the offending slice into
45
+ * the URL (so the link degrades to "unshared" rather than the page failing
46
+ * to load on refresh).
47
+ */
48
+ public static readonly MaxQueryStringLength: number = 4000;
49
+
50
+ public static getParamName(
20
51
  tableId: string,
21
52
  kind: TableFilterUrlStateKind,
22
53
  ): string {
23
54
  return `${tableId}-${kind}`;
24
55
  }
25
56
 
57
+ /**
58
+ * Keys currently claimed by mounted tables, so a duplicate can be reported.
59
+ * Not used to change behaviour — two tables sharing a key would already have
60
+ * shared their `userPreferencesKey` page-size preference, so the fix always
61
+ * belongs at the call site.
62
+ */
63
+ private static claimedKeys: Map<string, number> = new Map<string, number>();
64
+
65
+ /**
66
+ * Register a mounted table's URL namespace. Returns a release function to
67
+ * call on unmount.
68
+ *
69
+ * Two tables on one route claiming the same key would read and write the
70
+ * same params — paging one would repaginate the other, and a reload would
71
+ * restore whichever wrote last. That is always a call-site bug (give the
72
+ * tables distinct `userPreferencesKey`/`urlStateKey` values), so this warns
73
+ * loudly rather than silently renaming a key that may already be in
74
+ * someone's bookmarks.
75
+ */
76
+ public static claimKey(tableId: string | undefined): VoidFunction {
77
+ if (!tableId) {
78
+ return () => {
79
+ // nothing claimed
80
+ };
81
+ }
82
+
83
+ const claims: number = (this.claimedKeys.get(tableId) || 0) + 1;
84
+ this.claimedKeys.set(tableId, claims);
85
+
86
+ if (claims > 1) {
87
+ Logger.warn(
88
+ `TableFilterUrlState: ${claims} tables on this page share the URL state key "${tableId}". ` +
89
+ `They will overwrite each other's filters, sort and pagination in the URL. ` +
90
+ `Give each table a distinct "userPreferencesKey" (or pass "urlStateKey").`,
91
+ );
92
+ }
93
+
94
+ return () => {
95
+ const remaining: number = (this.claimedKeys.get(tableId) || 1) - 1;
96
+
97
+ if (remaining <= 0) {
98
+ this.claimedKeys.delete(tableId);
99
+ return;
100
+ }
101
+
102
+ this.claimedKeys.set(tableId, remaining);
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Test seam — drops every claim so one test's mounted tables don't leak into
108
+ * the next.
109
+ */
110
+ public static resetClaimedKeys(): void {
111
+ this.claimedKeys.clear();
112
+ }
113
+
114
+ /**
115
+ * Every param name this table could own. Used to clear a table's state and
116
+ * by tests.
117
+ */
118
+ public static getAllParamNames(tableId: string): Array<string> {
119
+ return TableFilterUrlStateKinds.map((kind: TableFilterUrlStateKind) => {
120
+ return this.getParamName(tableId, kind);
121
+ });
122
+ }
123
+
26
124
  /*
27
125
  * Read a previously-persisted snapshot from the URL. Returns null when absent,
28
126
  * empty, or unparseable (e.g. a hand-edited param) so callers fall back to
@@ -67,26 +165,115 @@ export default class TableFilterUrlState {
67
165
  tableId: string | undefined,
68
166
  kind: TableFilterUrlStateKind,
69
167
  state: JSONObject | null,
168
+ ): void {
169
+ this.writeMany(tableId, { [kind]: state });
170
+ }
171
+
172
+ /**
173
+ * Write several slices in one `history.replaceState` call. Passing a kind
174
+ * with a `null`/empty value removes that param; omitting a kind leaves
175
+ * whatever is already on the URL untouched.
176
+ */
177
+ public static writeMany(
178
+ tableId: string | undefined,
179
+ states: Partial<Record<TableFilterUrlStateKind, JSONObject | null>>,
70
180
  ): void {
71
181
  if (!tableId) {
72
182
  return;
73
183
  }
74
184
 
75
- try {
76
- const hasState: boolean = Boolean(state && Object.keys(state).length > 0);
185
+ const params: Dictionary<string | null> = {};
186
+
187
+ /*
188
+ * Track the query string as it would look after each param is applied, so
189
+ * the size check accounts for the other params in this same batch — not
190
+ * just the URL as it was before the batch started.
191
+ */
192
+ const projected: URLSearchParams = this.getCurrentSearchParams();
193
+
194
+ for (const kind of Object.keys(states) as Array<TableFilterUrlStateKind>) {
195
+ const state: JSONObject | null | undefined = states[kind];
196
+ const paramName: string = this.getParamName(tableId, kind);
197
+
198
+ let value: string | null = null;
199
+
200
+ try {
201
+ const hasState: boolean = Boolean(
202
+ state && Object.keys(state).length > 0,
203
+ );
77
204
 
78
- const value: string | null = hasState
79
- ? JSON.stringify(JSONFunctions.serialize(state as JSONObject))
80
- : null;
205
+ value = hasState
206
+ ? JSON.stringify(JSONFunctions.serialize(state as JSONObject))
207
+ : null;
208
+ } catch (err) {
209
+ /*
210
+ * Serialization failure (shouldn't happen for filter data) — drop the
211
+ * param rather than break the table, and leave a breadcrumb.
212
+ */
213
+ Logger.warn(
214
+ `TableFilterUrlState: could not serialize "${paramName}": ${err}`,
215
+ );
216
+ value = null;
217
+ }
218
+
219
+ if (value === null) {
220
+ projected.delete(paramName);
221
+ } else {
222
+ const previous: string | null = projected.get(paramName);
223
+ projected.set(paramName, value);
224
+
225
+ if (projected.toString().length > this.MaxQueryStringLength) {
226
+ /*
227
+ * Too big to share. Drop the param so a page refresh doesn't hit an
228
+ * over-long request line — React state remains the source of truth
229
+ * for this session.
230
+ */
231
+ Logger.warn(
232
+ `TableFilterUrlState: "${paramName}" is too large for the URL (${value.length} chars) and was not persisted.`,
233
+ );
234
+ value = null;
235
+
236
+ if (previous === null) {
237
+ projected.delete(paramName);
238
+ } else {
239
+ projected.set(paramName, previous);
240
+ }
241
+ }
242
+ }
243
+
244
+ params[paramName] = value;
245
+ }
81
246
 
82
- Navigation.setQueryString({
83
- [this.getParamName(tableId, kind)]: value,
84
- });
247
+ Navigation.setQueryString(params);
248
+ }
249
+
250
+ /**
251
+ * Remove every param this table owns from the URL.
252
+ */
253
+ public static clear(tableId: string | undefined): void {
254
+ if (!tableId) {
255
+ return;
256
+ }
257
+
258
+ const params: Dictionary<string | null> = {};
259
+
260
+ for (const paramName of this.getAllParamNames(tableId)) {
261
+ params[paramName] = null;
262
+ }
263
+
264
+ Navigation.setQueryString(params);
265
+ }
266
+
267
+ /**
268
+ * The current query string as a mutable `URLSearchParams`. Size checks
269
+ * measure `toString()` on this — the *encoded* length, because that is what
270
+ * actually travels on the wire.
271
+ */
272
+ private static getCurrentSearchParams(): URLSearchParams {
273
+ try {
274
+ return new URLSearchParams(Navigation.getQueryString());
85
275
  } catch {
86
- /*
87
- * Serialization failure (shouldn't happen for filter data) — skip the
88
- * URL sync rather than break the table.
89
- */
276
+ return new URLSearchParams();
90
277
  }
91
278
  }
92
279
  }
@@ -0,0 +1,165 @@
1
+ import { JSONObject } from "../../Types/JSON";
2
+ import SortOrder from "../../Types/BaseDatabase/SortOrder";
3
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
4
+
5
+ /**
6
+ * The "everything that isn't a column filter or a facet" slice of a table's
7
+ * view: the search box, the label chips next to it, the active sort and where
8
+ * in the pagination the user is.
9
+ *
10
+ * Kept deliberately primitive (strings / numbers / string arrays) so the URL
11
+ * param stays short and human-readable, and so a hand-edited link can never
12
+ * smuggle a typed object into the table's query.
13
+ */
14
+ export interface TableViewUrlStateData {
15
+ search?: string | undefined;
16
+ labels?: Array<string> | undefined;
17
+ sortBy?: string | undefined;
18
+ sortOrder?: SortOrder | undefined;
19
+ page?: number | undefined;
20
+ itemsOnPage?: number | undefined;
21
+ }
22
+
23
+ /**
24
+ * The values a slice is compared against before being written. Anything equal
25
+ * to its default is left out of the URL, so a table the user hasn't touched
26
+ * contributes no query params at all.
27
+ */
28
+ export interface TableViewUrlStateDefaults {
29
+ sortBy?: string | undefined;
30
+ sortOrder?: SortOrder | undefined;
31
+ }
32
+
33
+ /**
34
+ * Hard ceiling on a restored page size. Anything above this is a hand-edited
35
+ * URL trying to make the table ask the API for an unbounded page.
36
+ */
37
+ export const MaxItemsOnPage: number = 1000;
38
+
39
+ export default class TableViewUrlState {
40
+ /**
41
+ * Serialize to the plain object that goes in the URL, omitting every value
42
+ * that matches its default. Returns `null` when nothing is worth persisting
43
+ * so the caller can drop the param entirely.
44
+ */
45
+ public static toJSON(
46
+ state: TableViewUrlStateData,
47
+ defaults?: TableViewUrlStateDefaults | undefined,
48
+ ): JSONObject | null {
49
+ const json: JSONObject = {};
50
+
51
+ const search: string = (state.search || "").trim();
52
+ if (search.length > 0) {
53
+ json["search"] = search;
54
+ }
55
+
56
+ const labels: Array<string> = (state.labels || []).filter((l: string) => {
57
+ return Boolean(l);
58
+ });
59
+ if (labels.length > 0) {
60
+ json["labels"] = labels;
61
+ }
62
+
63
+ /*
64
+ * Sort is only worth persisting when it differs from the sort the table
65
+ * was mounted with — otherwise every table on the page would carry a
66
+ * redundant param.
67
+ */
68
+ const sortIsDefault: boolean =
69
+ (state.sortBy || null) === (defaults?.sortBy || null) &&
70
+ (state.sortOrder || null) === (defaults?.sortOrder || null);
71
+
72
+ if (state.sortBy && !sortIsDefault) {
73
+ json["sortBy"] = state.sortBy;
74
+ json["sortOrder"] = state.sortOrder || SortOrder.Ascending;
75
+ }
76
+
77
+ if (state.page && state.page > 1) {
78
+ json["page"] = state.page;
79
+ }
80
+
81
+ if (state.itemsOnPage && state.itemsOnPage > 0) {
82
+ json["itemsOnPage"] = state.itemsOnPage;
83
+ }
84
+
85
+ if (Object.keys(json).length === 0) {
86
+ return null;
87
+ }
88
+
89
+ return json;
90
+ }
91
+
92
+ /**
93
+ * Rebuild the view state from a URL param. Every field is validated
94
+ * independently: a bad `page` doesn't discard a good `search`, and an
95
+ * unrecognised value is dropped rather than passed through to the query.
96
+ */
97
+ public static fromJSON(
98
+ json: JSONObject | null | undefined,
99
+ ): TableViewUrlStateData {
100
+ const state: TableViewUrlStateData = {};
101
+
102
+ if (!json || typeof json !== "object") {
103
+ return state;
104
+ }
105
+
106
+ if (typeof json["search"] === "string" && json["search"].trim() !== "") {
107
+ state.search = json["search"];
108
+ }
109
+
110
+ if (Array.isArray(json["labels"])) {
111
+ const labels: Array<string> = (json["labels"] as Array<unknown>)
112
+ .filter((l: unknown) => {
113
+ return typeof l === "string" && l.trim() !== "";
114
+ })
115
+ .map((l: unknown) => {
116
+ return l as string;
117
+ });
118
+
119
+ if (labels.length > 0) {
120
+ state.labels = labels;
121
+ }
122
+ }
123
+
124
+ if (typeof json["sortBy"] === "string" && json["sortBy"].trim() !== "") {
125
+ state.sortBy = json["sortBy"];
126
+
127
+ state.sortOrder =
128
+ json["sortOrder"] === SortOrder.Descending
129
+ ? SortOrder.Descending
130
+ : SortOrder.Ascending;
131
+ }
132
+
133
+ const page: number | null = this.toPositiveInteger(json["page"]);
134
+ if (page !== null && page >= 1) {
135
+ state.page = page;
136
+ }
137
+
138
+ const itemsOnPage: number | null = this.toPositiveInteger(
139
+ json["itemsOnPage"],
140
+ );
141
+ if (
142
+ itemsOnPage !== null &&
143
+ itemsOnPage >= 1 &&
144
+ itemsOnPage <= MaxItemsOnPage
145
+ ) {
146
+ state.itemsOnPage = itemsOnPage;
147
+ }
148
+
149
+ return state;
150
+ }
151
+
152
+ private static toPositiveInteger(value: unknown): number | null {
153
+ if (typeof value !== "number" || !isFinite(value)) {
154
+ return null;
155
+ }
156
+
157
+ const asInteger: number = Math.floor(value);
158
+
159
+ if (asInteger < 1 || asInteger > LIMIT_MAX) {
160
+ return null;
161
+ }
162
+
163
+ return asInteger;
164
+ }
165
+ }