@oneuptime/common 11.7.2 → 11.7.4

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 (414) hide show
  1. package/Models/AnalyticsModels/KubernetesCostAllocation.ts +103 -0
  2. package/Models/DatabaseModels/AlertEpisodeStateTimeline.ts +1 -0
  3. package/Models/DatabaseModels/AlertStateTimeline.ts +1 -0
  4. package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
  5. package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
  6. package/Models/DatabaseModels/Index.ts +5 -0
  7. package/Models/DatabaseModels/LogDropFilter.ts +89 -0
  8. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +13 -3
  9. package/Models/DatabaseModels/RecommendationDismissal.ts +463 -0
  10. package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
  11. package/Models/DatabaseModels/StatusPageGroup.ts +95 -0
  12. package/Models/DatabaseModels/TableView.ts +40 -0
  13. package/Models/DatabaseModels/TraceDropFilter.ts +89 -0
  14. package/Models/DatabaseModels/WorkflowVariable.ts +5 -1
  15. package/Server/API/AlertAPI.ts +32 -17
  16. package/Server/API/BaseAPI.ts +31 -2
  17. package/Server/API/BaseAnalyticsAPI.ts +36 -2
  18. package/Server/API/CommonAPI.ts +57 -0
  19. package/Server/API/IncidentAPI.ts +60 -33
  20. package/Server/API/IncidentEpisodeAPI.ts +31 -16
  21. package/Server/API/MonitorAPI.ts +30 -0
  22. package/Server/API/MonitorTemplateAPI.ts +8 -0
  23. package/Server/API/ProbeAPI.ts +196 -15
  24. package/Server/API/ProjectAPI.ts +79 -1
  25. package/Server/API/ScheduledMaintenanceAPI.ts +33 -18
  26. package/Server/API/StatusPageAPI.ts +74 -37
  27. package/Server/API/WorkspaceNotificationRuleAPI.ts +34 -4
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.ts +13 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.ts +527 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.ts +31 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.ts +55 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.ts +53 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  34. package/Server/Services/AlertEpisodeService.ts +47 -0
  35. package/Server/Services/AlertService.ts +125 -0
  36. package/Server/Services/BillingService.ts +98 -0
  37. package/Server/Services/DatabaseService.ts +184 -20
  38. package/Server/Services/IncidentEpisodeService.ts +47 -0
  39. package/Server/Services/IncidentService.ts +123 -0
  40. package/Server/Services/IncidentTemplateService.ts +123 -1
  41. package/Server/Services/Index.ts +2 -0
  42. package/Server/Services/LogDropFilterService.ts +133 -0
  43. package/Server/Services/MonitorProbeService.ts +94 -4
  44. package/Server/Services/MonitorService.ts +48 -43
  45. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +70 -0
  46. package/Server/Services/ProbeService.ts +66 -0
  47. package/Server/Services/ProjectService.ts +131 -7
  48. package/Server/Services/RecommendationDismissalService.ts +52 -0
  49. package/Server/Services/RunbookAgentJobService.ts +68 -7
  50. package/Server/Services/ScheduledMaintenanceService.ts +103 -0
  51. package/Server/Services/ScheduledMaintenanceTemplateService.ts +90 -0
  52. package/Server/Services/StatusPageGroupService.ts +186 -0
  53. package/Server/Services/TraceDropFilterService.ts +133 -0
  54. package/Server/Types/Workflow/Components/API/Delete.ts +12 -0
  55. package/Server/Types/Workflow/Components/API/Get.ts +12 -0
  56. package/Server/Types/Workflow/Components/API/Patch.ts +12 -0
  57. package/Server/Types/Workflow/Components/API/Post.ts +12 -0
  58. package/Server/Types/Workflow/Components/API/Put.ts +13 -0
  59. package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +212 -0
  60. package/Server/Utils/DropFilterValidation.ts +127 -0
  61. package/Server/Utils/Errors.ts +5 -0
  62. package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
  63. package/Server/Utils/Monitor/MonitorIncident.ts +31 -2
  64. package/Server/Utils/Telemetry/AppMetrics.ts +31 -0
  65. package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +16 -0
  66. package/Tests/Models/DatabaseModels/MonitorProbeColumnAccessControl.test.ts +196 -0
  67. package/Tests/Models/RecommendationDismissalModel.test.ts +269 -0
  68. package/Tests/Server/API/BaseAPIUpdatePayloadValidation.test.ts +320 -0
  69. package/Tests/Server/API/BaseAnalyticsAPIUpdatePayloadValidation.test.ts +293 -0
  70. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +164 -0
  71. package/Tests/Server/API/ProbeAPI.test.ts +422 -53
  72. package/Tests/Server/API/ProjectAPI.test.ts +180 -0
  73. package/Tests/Server/API/ProjectAPIExtendTrialBillingDisabled.test.ts +138 -0
  74. package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +458 -0
  75. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +359 -0
  76. package/Tests/Server/Infrastructure/ProcessSignalDelivery.test.ts +427 -0
  77. package/Tests/Server/Services/BillingServiceExtendTrial.test.ts +439 -0
  78. package/Tests/Server/Services/CrossProjectReferenceWriteGuard.test.ts +810 -0
  79. package/Tests/Server/Services/DatabaseServiceAtomicAddToColumns.test.ts +269 -0
  80. package/Tests/Server/Services/DatabaseServiceEmptyUpdate.test.ts +277 -0
  81. package/Tests/Server/Services/DatabaseServiceSortColumnSelect.test.ts +201 -0
  82. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +81 -23
  83. package/Tests/Server/Services/DropFilterSaveValidation.test.ts +398 -0
  84. package/Tests/Server/Services/MonitorProbeDeleteHooks.test.ts +280 -0
  85. package/Tests/Server/Services/MonitorProbeServiceProbeTenancy.test.ts +304 -0
  86. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +262 -0
  87. package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +614 -0
  88. package/Tests/Server/Services/RecommendationDismissalService.test.ts +306 -0
  89. package/Tests/Server/Services/RepairCrossProjectIncidentReferencesMigration.test.ts +528 -0
  90. package/Tests/Server/Services/StatusPageGroupNesting.test.ts +395 -0
  91. package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +26 -21
  92. package/Tests/Server/Types/Database/Permissions/WorkflowVariableColumnPermission.test.ts +227 -0
  93. package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +285 -0
  94. package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +463 -0
  95. package/Tests/Server/Utils/DropFilterValidation.test.ts +269 -0
  96. package/Tests/Server/Utils/Telemetry/SpanUtil.test.ts +94 -0
  97. package/Tests/Types/DateUserTimezone.test.ts +52 -0
  98. package/Tests/Types/JSONFunctions.test.ts +103 -1
  99. package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +177 -9
  100. package/Tests/Types/Monitor/MonitorStepDnsMonitor.test.ts +105 -0
  101. package/Tests/Types/Monitor/MonitorStepDnssecMonitor.test.ts +131 -0
  102. package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +60 -0
  103. package/Tests/Types/Monitor/MonitorStepExternalStatusPageMonitor.test.ts +82 -0
  104. package/Tests/Types/Monitor/MonitorStepInfrastructureMonitors.test.ts +268 -0
  105. package/Tests/Types/Monitor/MonitorStepMetricMonitor.test.ts +386 -0
  106. package/Tests/Types/Monitor/MonitorStepProfileMonitor.test.ts +185 -0
  107. package/Tests/Types/Monitor/MonitorStepSnmpMonitor.test.ts +156 -0
  108. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +371 -0
  109. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +901 -0
  110. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +607 -0
  111. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +754 -0
  112. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +960 -0
  113. package/Tests/Types/RollingTime/RollingTimeUtil.test.ts +186 -0
  114. package/Tests/Types/Runbook/RunbookStepTimeout.test.ts +410 -0
  115. package/Tests/Types/Telemetry/DropFilterSampling.test.ts +241 -0
  116. package/Tests/Types/Workspace/NotificationRuleConditionUtil.test.ts +353 -0
  117. package/Tests/Types/Workspace/NotificationRuleUtil.test.ts +566 -0
  118. package/Tests/UI/Components/CodeEditor.test.tsx +174 -0
  119. package/Tests/UI/Components/ErrorBoundary.test.tsx +555 -24
  120. package/Tests/UI/Components/InfoCard.test.tsx +358 -0
  121. package/Tests/UI/Components/LogTimeRangePicker.test.tsx +138 -0
  122. package/Tests/UI/Components/Modal.test.tsx +43 -5
  123. package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +679 -0
  124. package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +397 -0
  125. package/Tests/UI/Components/ModelTable/ColumnCustomizationModal.test.tsx +999 -0
  126. package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +1678 -0
  127. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1094 -0
  128. package/Tests/UI/Components/Runbook/StepTimeoutInput.test.tsx +386 -0
  129. package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +671 -0
  130. package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +404 -0
  131. package/Tests/UI/Utils/DropdownAlignment.test.ts +306 -0
  132. package/Tests/UI/Utils/TableFilterUrlState.test.ts +292 -0
  133. package/Tests/Utils/Monitor/MonitorSummaryProbeUtil.test.ts +263 -0
  134. package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +583 -0
  135. package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +1072 -0
  136. package/Tests/Utils/StatusPage/GroupTree.test.ts +583 -0
  137. package/Tests/Utils/StatusPage/ResourceUptime.test.ts +411 -0
  138. package/Tests/Utils/UserPreferences.test.ts +563 -0
  139. package/Types/Date.ts +15 -6
  140. package/Types/JSONFunctions.ts +7 -2
  141. package/Types/Kubernetes/KubernetesCostIngest.ts +37 -1
  142. package/Types/Monitor/KubernetesAlertTemplates.ts +205 -0
  143. package/Types/Monitor/MonitorStep.ts +10 -1
  144. package/Types/Monitor/MonitorStepMetricMonitor.ts +46 -1
  145. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +413 -0
  146. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +168 -0
  147. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +175 -0
  148. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +743 -0
  149. package/Types/Permission.ts +45 -0
  150. package/Types/Recommendation/RecommendationType.ts +20 -0
  151. package/Types/Runbook/RunbookExecutionDeadline.ts +129 -0
  152. package/Types/Runbook/RunbookStepTimeout.ts +202 -0
  153. package/Types/Telemetry/DropFilterSampling.ts +92 -0
  154. package/UI/Components/AI/GenerateFromAIModal.tsx +0 -2
  155. package/UI/Components/Accordion/Accordion.tsx +10 -2
  156. package/UI/Components/BulkUpdate/BulkLabelActions.tsx +0 -1
  157. package/UI/Components/CodeEditor/CodeEditor.tsx +34 -20
  158. package/UI/Components/Date/RangeStartAndEndDateView.tsx +0 -1
  159. package/UI/Components/EditionLabel/EditionLabel.tsx +1 -27
  160. package/UI/Components/Error/PageError.tsx +0 -4
  161. package/UI/Components/ErrorBoundary.tsx +252 -15
  162. package/UI/Components/InfoCard/InfoCard.tsx +58 -1
  163. package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +34 -1
  164. package/UI/Components/MasterPage/MasterPage.tsx +65 -0
  165. package/UI/Components/Modal/Modal.tsx +16 -60
  166. package/UI/Components/ModelFormModal/ModelFormModal.tsx +0 -8
  167. package/UI/Components/ModelTable/BaseModelTable.tsx +503 -71
  168. package/UI/Components/ModelTable/Column.ts +17 -0
  169. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +523 -0
  170. package/UI/Components/ModelTable/ColumnPreference.ts +482 -0
  171. package/UI/Components/ModelTable/CustomFieldColumns.tsx +326 -0
  172. package/UI/Components/ModelTable/TableView.tsx +24 -2
  173. package/UI/Components/ModelTable/useCustomFieldColumns.ts +150 -0
  174. package/UI/Components/Runbook/StepTimeoutInput.tsx +173 -0
  175. package/UI/Components/SideMenu/SideMenu.tsx +24 -4
  176. package/UI/Components/StatusPage/ResourceGroupSection.tsx +231 -0
  177. package/UI/Components/Table/Table.tsx +14 -1
  178. package/UI/Components/Table/TableRow.tsx +180 -175
  179. package/UI/Components/Table/Types/Column.ts +2 -0
  180. package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +34 -1
  181. package/UI/Utils/DropdownAlignment.ts +162 -0
  182. package/UI/Utils/TableFilterUrlState.ts +59 -20
  183. package/Utils/API.ts +106 -2
  184. package/Utils/Monitor/MonitorSummaryProbeUtil.ts +130 -0
  185. package/Utils/NetworkDiscovery/ScanTargetUtil.ts +434 -0
  186. package/Utils/StatusPage/GroupNestingLayout.ts +343 -0
  187. package/Utils/StatusPage/GroupTree.ts +307 -0
  188. package/Utils/StatusPage/ResourceUptime.ts +90 -17
  189. package/Utils/UserPreferences.ts +53 -0
  190. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +86 -0
  191. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -1
  192. package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js +1 -0
  193. package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js.map +1 -1
  194. package/build/dist/Models/DatabaseModels/AlertStateTimeline.js +1 -0
  195. package/build/dist/Models/DatabaseModels/AlertStateTimeline.js.map +1 -1
  196. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
  197. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
  198. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
  199. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
  200. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  201. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  202. package/build/dist/Models/DatabaseModels/LogDropFilter.js +91 -0
  203. package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
  204. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +14 -4
  205. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  206. package/build/dist/Models/DatabaseModels/RecommendationDismissal.js +484 -0
  207. package/build/dist/Models/DatabaseModels/RecommendationDismissal.js.map +1 -0
  208. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
  209. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
  210. package/build/dist/Models/DatabaseModels/StatusPageGroup.js +94 -0
  211. package/build/dist/Models/DatabaseModels/StatusPageGroup.js.map +1 -1
  212. package/build/dist/Models/DatabaseModels/TableView.js +40 -0
  213. package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
  214. package/build/dist/Models/DatabaseModels/TraceDropFilter.js +91 -0
  215. package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
  216. package/build/dist/Models/DatabaseModels/WorkflowVariable.js +5 -1
  217. package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
  218. package/build/dist/Server/API/AlertAPI.js +22 -13
  219. package/build/dist/Server/API/AlertAPI.js.map +1 -1
  220. package/build/dist/Server/API/BaseAPI.js +22 -1
  221. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  222. package/build/dist/Server/API/BaseAnalyticsAPI.js +24 -1
  223. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  224. package/build/dist/Server/API/CommonAPI.js +42 -0
  225. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  226. package/build/dist/Server/API/IncidentAPI.js +43 -26
  227. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  228. package/build/dist/Server/API/IncidentEpisodeAPI.js +21 -12
  229. package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
  230. package/build/dist/Server/API/MonitorAPI.js +23 -0
  231. package/build/dist/Server/API/MonitorAPI.js.map +1 -1
  232. package/build/dist/Server/API/MonitorTemplateAPI.js +4 -0
  233. package/build/dist/Server/API/MonitorTemplateAPI.js.map +1 -1
  234. package/build/dist/Server/API/ProbeAPI.js +131 -15
  235. package/build/dist/Server/API/ProbeAPI.js.map +1 -1
  236. package/build/dist/Server/API/ProjectAPI.js +62 -3
  237. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  238. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +23 -14
  239. package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
  240. package/build/dist/Server/API/StatusPageAPI.js +61 -33
  241. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  242. package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js +26 -2
  243. package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js.map +1 -1
  244. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js +12 -0
  245. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js.map +1 -0
  246. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js +397 -0
  247. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js.map +1 -0
  248. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js +16 -0
  249. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js.map +1 -0
  250. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js +30 -0
  251. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js.map +1 -0
  252. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js +34 -0
  253. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js.map +1 -0
  254. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  255. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  256. package/build/dist/Server/Services/AlertEpisodeService.js +39 -0
  257. package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
  258. package/build/dist/Server/Services/AlertService.js +95 -0
  259. package/build/dist/Server/Services/AlertService.js.map +1 -1
  260. package/build/dist/Server/Services/BillingService.js +71 -0
  261. package/build/dist/Server/Services/BillingService.js.map +1 -1
  262. package/build/dist/Server/Services/DatabaseService.js +140 -17
  263. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  264. package/build/dist/Server/Services/IncidentEpisodeService.js +39 -0
  265. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  266. package/build/dist/Server/Services/IncidentService.js +100 -0
  267. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  268. package/build/dist/Server/Services/IncidentTemplateService.js +97 -0
  269. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  270. package/build/dist/Server/Services/Index.js +2 -0
  271. package/build/dist/Server/Services/Index.js.map +1 -1
  272. package/build/dist/Server/Services/LogDropFilterService.js +93 -0
  273. package/build/dist/Server/Services/LogDropFilterService.js.map +1 -1
  274. package/build/dist/Server/Services/MonitorProbeService.js +73 -5
  275. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  276. package/build/dist/Server/Services/MonitorService.js +34 -39
  277. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  278. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +71 -0
  279. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  280. package/build/dist/Server/Services/ProbeService.js +64 -0
  281. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  282. package/build/dist/Server/Services/ProjectService.js +103 -7
  283. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  284. package/build/dist/Server/Services/RecommendationDismissalService.js +50 -0
  285. package/build/dist/Server/Services/RecommendationDismissalService.js.map +1 -0
  286. package/build/dist/Server/Services/RunbookAgentJobService.js +63 -5
  287. package/build/dist/Server/Services/RunbookAgentJobService.js.map +1 -1
  288. package/build/dist/Server/Services/ScheduledMaintenanceService.js +83 -0
  289. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  290. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +65 -0
  291. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
  292. package/build/dist/Server/Services/StatusPageGroupService.js +136 -0
  293. package/build/dist/Server/Services/StatusPageGroupService.js.map +1 -1
  294. package/build/dist/Server/Services/TraceDropFilterService.js +93 -0
  295. package/build/dist/Server/Services/TraceDropFilterService.js.map +1 -1
  296. package/build/dist/Server/Types/Workflow/Components/API/Delete.js +11 -0
  297. package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
  298. package/build/dist/Server/Types/Workflow/Components/API/Get.js +11 -0
  299. package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
  300. package/build/dist/Server/Types/Workflow/Components/API/Patch.js +11 -0
  301. package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
  302. package/build/dist/Server/Types/Workflow/Components/API/Post.js +11 -0
  303. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  304. package/build/dist/Server/Types/Workflow/Components/API/Put.js +12 -0
  305. package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
  306. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +132 -0
  307. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -0
  308. package/build/dist/Server/Utils/DropFilterValidation.js +80 -0
  309. package/build/dist/Server/Utils/DropFilterValidation.js.map +1 -0
  310. package/build/dist/Server/Utils/Errors.js +3 -0
  311. package/build/dist/Server/Utils/Errors.js.map +1 -1
  312. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +30 -12
  313. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  314. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +38 -18
  315. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  316. package/build/dist/Server/Utils/Telemetry/AppMetrics.js +26 -0
  317. package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
  318. package/build/dist/Types/Date.js +14 -4
  319. package/build/dist/Types/Date.js.map +1 -1
  320. package/build/dist/Types/JSONFunctions.js +8 -3
  321. package/build/dist/Types/JSONFunctions.js.map +1 -1
  322. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -1
  323. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +192 -0
  324. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  325. package/build/dist/Types/Monitor/MonitorStep.js +6 -1
  326. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  327. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js +32 -1
  328. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js.map +1 -1
  329. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +294 -0
  330. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -0
  331. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +110 -0
  332. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -0
  333. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +58 -0
  334. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -0
  335. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +451 -0
  336. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -0
  337. package/build/dist/Types/Permission.js +40 -0
  338. package/build/dist/Types/Permission.js.map +1 -1
  339. package/build/dist/Types/Recommendation/RecommendationType.js +21 -0
  340. package/build/dist/Types/Recommendation/RecommendationType.js.map +1 -0
  341. package/build/dist/Types/Runbook/RunbookExecutionDeadline.js +93 -0
  342. package/build/dist/Types/Runbook/RunbookExecutionDeadline.js.map +1 -0
  343. package/build/dist/Types/Runbook/RunbookStepTimeout.js +142 -0
  344. package/build/dist/Types/Runbook/RunbookStepTimeout.js.map +1 -0
  345. package/build/dist/Types/Telemetry/DropFilterSampling.js +75 -0
  346. package/build/dist/Types/Telemetry/DropFilterSampling.js.map +1 -0
  347. package/build/dist/UI/Components/AI/GenerateFromAIModal.js +1 -2
  348. package/build/dist/UI/Components/AI/GenerateFromAIModal.js.map +1 -1
  349. package/build/dist/UI/Components/Accordion/Accordion.js +9 -2
  350. package/build/dist/UI/Components/Accordion/Accordion.js.map +1 -1
  351. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js +1 -1
  352. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js.map +1 -1
  353. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +27 -14
  354. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  355. package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js +1 -1
  356. package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js.map +1 -1
  357. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +2 -20
  358. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  359. package/build/dist/UI/Components/Error/PageError.js +1 -3
  360. package/build/dist/UI/Components/Error/PageError.js.map +1 -1
  361. package/build/dist/UI/Components/ErrorBoundary.js +145 -11
  362. package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
  363. package/build/dist/UI/Components/InfoCard/InfoCard.js +28 -1
  364. package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
  365. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +13 -2
  366. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
  367. package/build/dist/UI/Components/MasterPage/MasterPage.js +50 -1
  368. package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
  369. package/build/dist/UI/Components/Modal/Modal.js +4 -32
  370. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  371. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
  372. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +308 -40
  373. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  374. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +230 -0
  375. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -0
  376. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +258 -0
  377. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -0
  378. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +168 -0
  379. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -0
  380. package/build/dist/UI/Components/ModelTable/TableView.js +13 -2
  381. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  382. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +84 -0
  383. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -0
  384. package/build/dist/UI/Components/Runbook/StepTimeoutInput.js +101 -0
  385. package/build/dist/UI/Components/Runbook/StepTimeoutInput.js.map +1 -0
  386. package/build/dist/UI/Components/SideMenu/SideMenu.js +15 -5
  387. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  388. package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js +73 -0
  389. package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js.map +1 -0
  390. package/build/dist/UI/Components/Table/Table.js +15 -2
  391. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  392. package/build/dist/UI/Components/Table/TableRow.js +11 -6
  393. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  394. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +13 -2
  395. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
  396. package/build/dist/UI/Utils/DropdownAlignment.js +98 -0
  397. package/build/dist/UI/Utils/DropdownAlignment.js.map +1 -0
  398. package/build/dist/UI/Utils/TableFilterUrlState.js +48 -15
  399. package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
  400. package/build/dist/Utils/API.js +39 -2
  401. package/build/dist/Utils/API.js.map +1 -1
  402. package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js +97 -0
  403. package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js.map +1 -0
  404. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +330 -0
  405. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -0
  406. package/build/dist/Utils/StatusPage/GroupNestingLayout.js +280 -0
  407. package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -0
  408. package/build/dist/Utils/StatusPage/GroupTree.js +214 -0
  409. package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -0
  410. package/build/dist/Utils/StatusPage/ResourceUptime.js +60 -16
  411. package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
  412. package/build/dist/Utils/UserPreferences.js +33 -0
  413. package/build/dist/Utils/UserPreferences.js.map +1 -1
  414. package/package.json +1 -1
@@ -0,0 +1,241 @@
1
+ import {
2
+ isSamplePercentageConfigured,
3
+ KEEP_ALL_PERCENTAGE,
4
+ MAX_SAMPLE_PERCENTAGE,
5
+ MIN_SAMPLE_PERCENTAGE,
6
+ resolveSamplePercentage,
7
+ shouldDropBySampling,
8
+ } from "../../../Types/Telemetry/DropFilterSampling";
9
+ import { describe, expect, it } from "@jest/globals";
10
+
11
+ /*
12
+ * Contract under test — how a drop filter's `samplePercentage` turns into a
13
+ * keep/discard decision.
14
+ *
15
+ * This replaced `filter.samplePercentage || 50`, duplicated in the log and
16
+ * trace drop-filter engines. That expression silently destroyed data three
17
+ * ways, and each one has a test below:
18
+ *
19
+ * 1. `samplePercentage` is nullable with no default and its form field was
20
+ * optional, so an UNSET percentage meant "discard half of every
21
+ * matching record" — a number nobody chose.
22
+ * 2. A stored `0` is falsy, so it was indistinguishable from unset and
23
+ * also kept 50%, contradicting both the literal reading ("keep 0%") and
24
+ * the view page's display of "0% kept".
25
+ * 3. Two copies of the expression could drift apart.
26
+ *
27
+ * The rule now is to fail SAFE: any percentage we cannot honour makes the
28
+ * filter a no-op rather than a shredder. `drop` exists for "discard
29
+ * everything matching", so nothing of value is lost by refusing to guess.
30
+ */
31
+
32
+ describe("resolveSamplePercentage", () => {
33
+ it("honours a percentage inside the usable range", () => {
34
+ expect(resolveSamplePercentage(1)).toBe(1);
35
+ expect(resolveSamplePercentage(10)).toBe(10);
36
+ expect(resolveSamplePercentage(50)).toBe(50);
37
+ expect(resolveSamplePercentage(99)).toBe(99);
38
+ });
39
+
40
+ it("honours a fractional percentage inside the range", () => {
41
+ expect(resolveSamplePercentage(0.5)).toBe(0.5);
42
+ expect(resolveSamplePercentage(99.9)).toBe(99.9);
43
+ });
44
+
45
+ /*
46
+ * The headline regression. `undefined || 50` was 50, so a sample filter
47
+ * saved with no percentage threw away roughly half of everything it
48
+ * matched, and nothing recorded that it had happened.
49
+ */
50
+ it("resolves an UNSET percentage to keep-everything, not the old 50", () => {
51
+ expect(resolveSamplePercentage(undefined)).toBe(KEEP_ALL_PERCENTAGE);
52
+ expect(resolveSamplePercentage(null)).toBe(KEEP_ALL_PERCENTAGE);
53
+ expect(resolveSamplePercentage(undefined)).not.toBe(50);
54
+ expect(resolveSamplePercentage(null)).not.toBe(50);
55
+ });
56
+
57
+ /*
58
+ * 0 never meant "keep nothing" in any shipped version — it was falsy, so
59
+ * it kept half. Honouring it literally now would start deleting data that
60
+ * used to survive, so it is treated as misconfigured instead.
61
+ */
62
+ it("treats 0 as misconfigured rather than 'discard everything'", () => {
63
+ expect(resolveSamplePercentage(0)).toBe(KEEP_ALL_PERCENTAGE);
64
+ });
65
+
66
+ it("treats a negative percentage as misconfigured", () => {
67
+ expect(resolveSamplePercentage(-1)).toBe(KEEP_ALL_PERCENTAGE);
68
+ expect(resolveSamplePercentage(-100)).toBe(KEEP_ALL_PERCENTAGE);
69
+ });
70
+
71
+ it("clamps 100 and above to keep-everything", () => {
72
+ expect(resolveSamplePercentage(100)).toBe(KEEP_ALL_PERCENTAGE);
73
+ expect(resolveSamplePercentage(1000)).toBe(KEEP_ALL_PERCENTAGE);
74
+ });
75
+
76
+ it("rejects non-finite numbers", () => {
77
+ expect(resolveSamplePercentage(NaN)).toBe(KEEP_ALL_PERCENTAGE);
78
+ expect(resolveSamplePercentage(Infinity)).toBe(KEEP_ALL_PERCENTAGE);
79
+ expect(resolveSamplePercentage(-Infinity)).toBe(KEEP_ALL_PERCENTAGE);
80
+ });
81
+
82
+ /*
83
+ * The column is nullable and typed `number`, but the value arrives through
84
+ * a bigint-free JSON boundary and a form. A string that happens to look
85
+ * like a number must not be treated as one — `"50" || 50` would have been
86
+ * "50", and `Math.random() * 100 >= "50"` coerces, so the old code would
87
+ * have sampled on a string. Now it fails safe.
88
+ */
89
+ it("rejects a value that is not a number at all", () => {
90
+ expect(resolveSamplePercentage("10" as unknown as number)).toBe(
91
+ KEEP_ALL_PERCENTAGE,
92
+ );
93
+ expect(resolveSamplePercentage({} as unknown as number)).toBe(
94
+ KEEP_ALL_PERCENTAGE,
95
+ );
96
+ expect(resolveSamplePercentage([] as unknown as number)).toBe(
97
+ KEEP_ALL_PERCENTAGE,
98
+ );
99
+ expect(resolveSamplePercentage(true as unknown as number)).toBe(
100
+ KEEP_ALL_PERCENTAGE,
101
+ );
102
+ });
103
+
104
+ it("accepts both ends of the range the validator enforces", () => {
105
+ expect(resolveSamplePercentage(MIN_SAMPLE_PERCENTAGE)).toBe(
106
+ MIN_SAMPLE_PERCENTAGE,
107
+ );
108
+ expect(resolveSamplePercentage(MAX_SAMPLE_PERCENTAGE)).toBe(
109
+ MAX_SAMPLE_PERCENTAGE,
110
+ );
111
+ });
112
+ });
113
+
114
+ describe("isSamplePercentageConfigured", () => {
115
+ it("is true only for a percentage the engine will actually sample on", () => {
116
+ expect(isSamplePercentageConfigured(1)).toBe(true);
117
+ expect(isSamplePercentageConfigured(50)).toBe(true);
118
+ expect(isSamplePercentageConfigured(99)).toBe(true);
119
+ });
120
+
121
+ /*
122
+ * This is what the view page keys off. It used to render `|| 0` as
123
+ * "0% kept / 100% discarded" for an unset percentage while the engine kept
124
+ * half — the display and the behaviour disagreed, and both were wrong.
125
+ */
126
+ it("is false for the values that used to render as '0% kept'", () => {
127
+ expect(isSamplePercentageConfigured(undefined)).toBe(false);
128
+ expect(isSamplePercentageConfigured(null)).toBe(false);
129
+ expect(isSamplePercentageConfigured(0)).toBe(false);
130
+ });
131
+
132
+ it("is false at and above 100, where sampling is a no-op", () => {
133
+ expect(isSamplePercentageConfigured(100)).toBe(false);
134
+ expect(isSamplePercentageConfigured(150)).toBe(false);
135
+ });
136
+ });
137
+
138
+ describe("shouldDropBySampling", () => {
139
+ /*
140
+ * `random` is injected so these are exact assertions rather than
141
+ * statistical ones. The engine keeps a record when
142
+ * `random() * 100 < keepPercentage`.
143
+ */
144
+ const fixedRandom: (value: number) => () => number = (
145
+ value: number,
146
+ ): (() => number) => {
147
+ return (): number => {
148
+ return value;
149
+ };
150
+ };
151
+
152
+ it("keeps a record when the draw lands inside the keep window", () => {
153
+ // 0.05 * 100 = 5, which is < 10, so this record is kept.
154
+ expect(shouldDropBySampling(10, fixedRandom(0.05))).toBe(false);
155
+ });
156
+
157
+ it("drops a record when the draw lands outside the keep window", () => {
158
+ // 0.5 * 100 = 50, which is >= 10, so this record is dropped.
159
+ expect(shouldDropBySampling(10, fixedRandom(0.5))).toBe(true);
160
+ });
161
+
162
+ it("drops exactly at the boundary, so keep-10% never keeps 11%", () => {
163
+ // >= is the comparison, so a draw of exactly the keep percentage drops.
164
+ expect(shouldDropBySampling(10, fixedRandom(0.1))).toBe(true);
165
+ });
166
+
167
+ it("keeps everything when the percentage is unset", () => {
168
+ for (const draw of [0, 0.25, 0.5, 0.75, 0.999]) {
169
+ expect(shouldDropBySampling(undefined, fixedRandom(draw))).toBe(false);
170
+ }
171
+ });
172
+
173
+ it("keeps everything when the percentage is 0", () => {
174
+ for (const draw of [0, 0.5, 0.999]) {
175
+ expect(shouldDropBySampling(0, fixedRandom(draw))).toBe(false);
176
+ }
177
+ });
178
+
179
+ /*
180
+ * A keep-everything filter should not even consume entropy: the cheap
181
+ * check has to come before the draw, because this runs once per ingested
182
+ * record on the hot path.
183
+ */
184
+ it("does not consult random at all when it is keeping everything", () => {
185
+ let calls: number = 0;
186
+ const countingRandom: () => number = (): number => {
187
+ calls++;
188
+ return 0.5;
189
+ };
190
+
191
+ expect(shouldDropBySampling(undefined, countingRandom)).toBe(false);
192
+ expect(shouldDropBySampling(0, countingRandom)).toBe(false);
193
+ expect(shouldDropBySampling(100, countingRandom)).toBe(false);
194
+ expect(calls).toBe(0);
195
+ });
196
+
197
+ it("consults random exactly once when it is sampling", () => {
198
+ let calls: number = 0;
199
+ const countingRandom: () => number = (): number => {
200
+ calls++;
201
+ return 0.5;
202
+ };
203
+
204
+ shouldDropBySampling(10, countingRandom);
205
+ expect(calls).toBe(1);
206
+ });
207
+
208
+ /*
209
+ * End-to-end sanity on the distribution, using a deterministic sweep
210
+ * rather than real randomness so this can never flake.
211
+ */
212
+ it("keeps approximately the requested share over a uniform sweep", () => {
213
+ const draws: Array<number> = [];
214
+ for (let i: number = 0; i < 1000; i++) {
215
+ draws.push(i / 1000);
216
+ }
217
+
218
+ for (const keepPercentage of [1, 10, 25, 50, 90, 99]) {
219
+ let kept: number = 0;
220
+ for (const draw of draws) {
221
+ if (!shouldDropBySampling(keepPercentage, fixedRandom(draw))) {
222
+ kept++;
223
+ }
224
+ }
225
+ // Exact for a uniform sweep of 1000 draws over [0, 1).
226
+ expect(kept / 10).toBeCloseTo(keepPercentage, 5);
227
+ }
228
+ });
229
+
230
+ it("defaults to Math.random when no generator is injected", () => {
231
+ // keep-99% over many real draws should keep at least one record.
232
+ let keptAtLeastOne: boolean = false;
233
+ for (let i: number = 0; i < 200; i++) {
234
+ if (!shouldDropBySampling(99)) {
235
+ keptAtLeastOne = true;
236
+ break;
237
+ }
238
+ }
239
+ expect(keptAtLeastOne).toBe(true);
240
+ });
241
+ });
@@ -0,0 +1,353 @@
1
+ import FilterCondition from "../../../Types/Filter/FilterCondition";
2
+ import NotificationRuleEventType from "../../../Types/Workspace/NotificationRules/EventType";
3
+ import {
4
+ ConditionType,
5
+ NotificationRuleConditionCheckOn,
6
+ NotificationRuleConditionUtil,
7
+ } from "../../../Types/Workspace/NotificationRules/NotificationRuleCondition";
8
+ import IncidentNotificationRule from "../../../Types/Workspace/NotificationRules/NotificationRuleTypes/IncidentNotificationRule";
9
+ import WorkspaceType from "../../../Types/Workspace/WorkspaceType";
10
+ import { describe, expect, it } from "@jest/globals";
11
+
12
+ /*
13
+ * NotificationRuleConditionUtil backs the workspace-notification-rule editor:
14
+ * getValidationError gates saving a rule, and the smaller helpers drive which
15
+ * inputs the form shows. A regression here either lets an unsavable rule
16
+ * through or hides the field the user needs, so the branches are pinned here.
17
+ */
18
+
19
+ function baseRule(
20
+ overrides: Partial<IncidentNotificationRule> = {},
21
+ ): IncidentNotificationRule {
22
+ return {
23
+ _type: "IncidentNotificationRule",
24
+ filterCondition: FilterCondition.All,
25
+ filters: [],
26
+ shouldCreateNewChannel: false,
27
+ shouldPostToExistingChannel: false,
28
+ existingChannelNames: "",
29
+ inviteTeamsToNewChannel: [],
30
+ inviteUsersToNewChannel: [],
31
+ shouldInviteOwnersToNewChannel: false,
32
+ newChannelTemplateName: "",
33
+ archiveChannelAutomatically: false,
34
+ shouldAutomaticallyInviteOnCallUsersToNewChannel: false,
35
+ ...overrides,
36
+ } as IncidentNotificationRule;
37
+ }
38
+
39
+ describe("NotificationRuleConditionUtil.getValidationError", () => {
40
+ it("requires a conditionType when a filter has a checkOn but no condition", () => {
41
+ const error: string | null =
42
+ NotificationRuleConditionUtil.getValidationError({
43
+ notificationRule: baseRule({
44
+ shouldCreateNewChannel: true,
45
+ newChannelTemplateName: "incident-{{id}}",
46
+ filters: [
47
+ {
48
+ checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
49
+ conditionType: undefined,
50
+ value: "x",
51
+ },
52
+ ],
53
+ }),
54
+ eventType: NotificationRuleEventType.Incident,
55
+ workspaceType: WorkspaceType.Slack,
56
+ });
57
+
58
+ expect(error).toBe(
59
+ `Filter Condition is required for ${NotificationRuleConditionCheckOn.IncidentTitle}`,
60
+ );
61
+ });
62
+
63
+ it("requires a value when a filter has checkOn and condition but no value", () => {
64
+ const error: string | null =
65
+ NotificationRuleConditionUtil.getValidationError({
66
+ notificationRule: baseRule({
67
+ shouldCreateNewChannel: true,
68
+ newChannelTemplateName: "incident-{{id}}",
69
+ filters: [
70
+ {
71
+ checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
72
+ conditionType: ConditionType.EqualTo,
73
+ value: undefined,
74
+ },
75
+ ],
76
+ }),
77
+ eventType: NotificationRuleEventType.Incident,
78
+ workspaceType: WorkspaceType.Slack,
79
+ });
80
+
81
+ expect(error).toBe(
82
+ `Value is required for ${NotificationRuleConditionCheckOn.IncidentTitle}`,
83
+ );
84
+ });
85
+
86
+ it("treats an empty array value as a missing value", () => {
87
+ const error: string | null =
88
+ NotificationRuleConditionUtil.getValidationError({
89
+ notificationRule: baseRule({
90
+ shouldCreateNewChannel: true,
91
+ newChannelTemplateName: "incident-{{id}}",
92
+ filters: [
93
+ {
94
+ checkOn: NotificationRuleConditionCheckOn.IncidentLabels,
95
+ conditionType: ConditionType.ContainsAny,
96
+ value: [],
97
+ },
98
+ ],
99
+ }),
100
+ eventType: NotificationRuleEventType.Incident,
101
+ workspaceType: WorkspaceType.Slack,
102
+ });
103
+
104
+ expect(error).toBe(
105
+ `Value is required for ${NotificationRuleConditionCheckOn.IncidentLabels}`,
106
+ );
107
+ });
108
+
109
+ it("requires a destination for incident rules when none is selected", () => {
110
+ const error: string | null =
111
+ NotificationRuleConditionUtil.getValidationError({
112
+ notificationRule: baseRule(),
113
+ eventType: NotificationRuleEventType.Incident,
114
+ workspaceType: WorkspaceType.Slack,
115
+ });
116
+
117
+ expect(error).toBe(
118
+ "Please select a destination: create a Slack channel or post to an existing Slack channel",
119
+ );
120
+ });
121
+
122
+ it("mentions the chat option for Microsoft Teams destinations", () => {
123
+ const error: string | null =
124
+ NotificationRuleConditionUtil.getValidationError({
125
+ notificationRule: baseRule(),
126
+ eventType: NotificationRuleEventType.Incident,
127
+ workspaceType: WorkspaceType.MicrosoftTeams,
128
+ });
129
+
130
+ expect(error).toBe(
131
+ "Please select a destination: create a Microsoft Teams channel, post to an existing Microsoft Teams channel, or post to an existing Microsoft Teams chat",
132
+ );
133
+ });
134
+
135
+ it("requires an existing channel name when posting to an existing channel", () => {
136
+ const error: string | null =
137
+ NotificationRuleConditionUtil.getValidationError({
138
+ notificationRule: baseRule({
139
+ shouldPostToExistingChannel: true,
140
+ existingChannelNames: " ",
141
+ }),
142
+ eventType: NotificationRuleEventType.Incident,
143
+ workspaceType: WorkspaceType.Slack,
144
+ });
145
+
146
+ expect(error).toBe("Existing Slack channel name is required");
147
+ });
148
+
149
+ it("requires a template name when creating a new channel", () => {
150
+ const error: string | null =
151
+ NotificationRuleConditionUtil.getValidationError({
152
+ notificationRule: baseRule({
153
+ shouldCreateNewChannel: true,
154
+ newChannelTemplateName: "",
155
+ }),
156
+ eventType: NotificationRuleEventType.Incident,
157
+ workspaceType: WorkspaceType.Slack,
158
+ });
159
+
160
+ expect(error).toBe("New Slack channel name is required");
161
+ });
162
+
163
+ it("requires at least one chat when posting to an existing chat", () => {
164
+ const error: string | null =
165
+ NotificationRuleConditionUtil.getValidationError({
166
+ notificationRule: baseRule({
167
+ shouldPostToExistingChat: true,
168
+ existingChatIds: [],
169
+ }),
170
+ eventType: NotificationRuleEventType.Incident,
171
+ workspaceType: WorkspaceType.MicrosoftTeams,
172
+ });
173
+
174
+ expect(error).toContain(
175
+ "Please select at least one Microsoft Teams chat to post to",
176
+ );
177
+ });
178
+
179
+ it("returns null for a fully valid rule that creates a channel", () => {
180
+ const error: string | null =
181
+ NotificationRuleConditionUtil.getValidationError({
182
+ notificationRule: baseRule({
183
+ shouldCreateNewChannel: true,
184
+ newChannelTemplateName: "incident-{{id}}",
185
+ filters: [
186
+ {
187
+ checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
188
+ conditionType: ConditionType.Contains,
189
+ value: "down",
190
+ },
191
+ ],
192
+ }),
193
+ eventType: NotificationRuleEventType.Incident,
194
+ workspaceType: WorkspaceType.Slack,
195
+ });
196
+
197
+ expect(error).toBeNull();
198
+ });
199
+ });
200
+
201
+ describe("NotificationRuleConditionUtil.hasValueField", () => {
202
+ it.each([
203
+ ConditionType.IsEmpty,
204
+ ConditionType.IsNotEmpty,
205
+ ConditionType.True,
206
+ ConditionType.False,
207
+ ])("hides the value field for %s", (conditionType: ConditionType) => {
208
+ expect(
209
+ NotificationRuleConditionUtil.hasValueField({
210
+ checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
211
+ conditionType,
212
+ }),
213
+ ).toBe(false);
214
+ });
215
+
216
+ it.each([
217
+ ConditionType.EqualTo,
218
+ ConditionType.Contains,
219
+ ConditionType.GreaterThan,
220
+ ConditionType.ContainsAll,
221
+ ])("shows the value field for %s", (conditionType: ConditionType) => {
222
+ expect(
223
+ NotificationRuleConditionUtil.hasValueField({
224
+ checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
225
+ conditionType,
226
+ }),
227
+ ).toBe(true);
228
+ });
229
+ });
230
+
231
+ describe("NotificationRuleConditionUtil.isDropdownValueField", () => {
232
+ it("returns false when checkOn or conditionType is missing", () => {
233
+ expect(
234
+ NotificationRuleConditionUtil.isDropdownValueField({
235
+ checkOn: undefined,
236
+ conditionType: ConditionType.ContainsAny,
237
+ }),
238
+ ).toBe(false);
239
+ expect(
240
+ NotificationRuleConditionUtil.isDropdownValueField({
241
+ checkOn: NotificationRuleConditionCheckOn.IncidentState,
242
+ conditionType: undefined,
243
+ }),
244
+ ).toBe(false);
245
+ });
246
+
247
+ it("returns true for enum/label-backed check-ons", () => {
248
+ expect(
249
+ NotificationRuleConditionUtil.isDropdownValueField({
250
+ checkOn: NotificationRuleConditionCheckOn.IncidentState,
251
+ conditionType: ConditionType.ContainsAny,
252
+ }),
253
+ ).toBe(true);
254
+ expect(
255
+ NotificationRuleConditionUtil.isDropdownValueField({
256
+ checkOn: NotificationRuleConditionCheckOn.MonitorLabels,
257
+ conditionType: ConditionType.ContainsAny,
258
+ }),
259
+ ).toBe(true);
260
+ });
261
+
262
+ it("returns false for free-text check-ons", () => {
263
+ expect(
264
+ NotificationRuleConditionUtil.isDropdownValueField({
265
+ checkOn: NotificationRuleConditionCheckOn.IncidentTitle,
266
+ conditionType: ConditionType.Contains,
267
+ }),
268
+ ).toBe(false);
269
+ });
270
+ });
271
+
272
+ describe("NotificationRuleConditionUtil.getCheckOnByEventType", () => {
273
+ it("returns incident-scoped check-ons for the Incident event", () => {
274
+ const checkOns: Array<NotificationRuleConditionCheckOn> =
275
+ NotificationRuleConditionUtil.getCheckOnByEventType(
276
+ NotificationRuleEventType.Incident,
277
+ );
278
+
279
+ expect(checkOns).toContain(NotificationRuleConditionCheckOn.IncidentTitle);
280
+ expect(checkOns).toContain(NotificationRuleConditionCheckOn.IncidentState);
281
+ // Alert-only check-ons must not leak into the incident editor.
282
+ expect(checkOns).not.toContain(NotificationRuleConditionCheckOn.AlertTitle);
283
+ });
284
+
285
+ it("returns monitor-scoped check-ons for the Monitor event", () => {
286
+ const checkOns: Array<NotificationRuleConditionCheckOn> =
287
+ NotificationRuleConditionUtil.getCheckOnByEventType(
288
+ NotificationRuleEventType.Monitor,
289
+ );
290
+
291
+ expect(checkOns).toContain(NotificationRuleConditionCheckOn.MonitorName);
292
+ expect(checkOns).toContain(NotificationRuleConditionCheckOn.MonitorStatus);
293
+ });
294
+
295
+ it("returns an empty list for an event type with no check-ons", () => {
296
+ expect(
297
+ NotificationRuleConditionUtil.getCheckOnByEventType(
298
+ NotificationRuleEventType.OnCallDutyPolicy,
299
+ ),
300
+ ).toEqual([]);
301
+ });
302
+ });
303
+
304
+ describe("NotificationRuleConditionUtil.getConditionTypeByCheckOn", () => {
305
+ it("offers text operators for free-text fields", () => {
306
+ const conditions: Array<ConditionType> =
307
+ NotificationRuleConditionUtil.getConditionTypeByCheckOn(
308
+ NotificationRuleConditionCheckOn.IncidentTitle,
309
+ );
310
+
311
+ expect(conditions).toEqual([
312
+ ConditionType.EqualTo,
313
+ ConditionType.NotEqualTo,
314
+ ConditionType.Contains,
315
+ ConditionType.NotContains,
316
+ ConditionType.StartsWith,
317
+ ConditionType.EndsWith,
318
+ ]);
319
+ });
320
+
321
+ it("offers set operators including ContainsAll for label fields", () => {
322
+ const conditions: Array<ConditionType> =
323
+ NotificationRuleConditionUtil.getConditionTypeByCheckOn(
324
+ NotificationRuleConditionCheckOn.IncidentLabels,
325
+ );
326
+
327
+ expect(conditions).toEqual([
328
+ ConditionType.ContainsAny,
329
+ ConditionType.NotContains,
330
+ ConditionType.ContainsAll,
331
+ ]);
332
+ });
333
+
334
+ it("offers only ContainsAny / NotContains for severity fields", () => {
335
+ const conditions: Array<ConditionType> =
336
+ NotificationRuleConditionUtil.getConditionTypeByCheckOn(
337
+ NotificationRuleConditionCheckOn.IncidentSeverity,
338
+ );
339
+
340
+ expect(conditions).toEqual([
341
+ ConditionType.ContainsAny,
342
+ ConditionType.NotContains,
343
+ ]);
344
+ });
345
+
346
+ it("returns an empty list for a check-on with no configured operators", () => {
347
+ expect(
348
+ NotificationRuleConditionUtil.getConditionTypeByCheckOn(
349
+ NotificationRuleConditionCheckOn.OnCallDutyPolicyName,
350
+ ),
351
+ ).toEqual([]);
352
+ });
353
+ });