@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,269 @@
1
+ import {
2
+ DropFilterCandidate,
3
+ DropFilterValidationOptions,
4
+ isSqlExpressionValue,
5
+ SAMPLE_ACTION,
6
+ validateDropFilter,
7
+ validateDropFilterFilterQuery,
8
+ validateDropFilterSamplePercentage,
9
+ } from "../../../Server/Utils/DropFilterValidation";
10
+ import BadDataException from "../../../Types/Exception/BadDataException";
11
+ import {
12
+ MAX_SAMPLE_PERCENTAGE,
13
+ MIN_SAMPLE_PERCENTAGE,
14
+ } from "../../../Types/Telemetry/DropFilterSampling";
15
+ import LogDropFilterAction from "../../../Types/Log/LogDropFilterAction";
16
+ import TraceDropFilterAction from "../../../Types/Trace/TraceDropFilterAction";
17
+ import { describe, expect, it } from "@jest/globals";
18
+
19
+ /*
20
+ * Contract under test — the save-time gate on drop filters.
21
+ *
22
+ * Both drop-filter models used to accept configurations the ingest engine
23
+ * could not honour, and both failed silently AND destructively:
24
+ *
25
+ * - A blank `filterQuery` compiles to "match every record", so saving a
26
+ * drop filter with an empty query discarded 100% of a project's
27
+ * telemetry with nothing to notice it by.
28
+ * - `action = "sample"` could be saved with no percentage, which the engine
29
+ * read as "throw away half".
30
+ *
31
+ * The API boundary is the only place a human is present to read the error,
32
+ * which is why this runs on create and on update rather than only in the
33
+ * dashboard form.
34
+ */
35
+
36
+ const LOGS: DropFilterValidationOptions = { recordNoun: "logs" };
37
+ const SPANS: DropFilterValidationOptions = { recordNoun: "spans" };
38
+
39
+ function candidate(
40
+ overrides: Partial<DropFilterCandidate>,
41
+ ): DropFilterCandidate {
42
+ return {
43
+ action: "drop",
44
+ samplePercentage: null,
45
+ filterQuery: "severityText = 'Error'",
46
+ ...overrides,
47
+ };
48
+ }
49
+
50
+ describe("drop filter action vocabulary", () => {
51
+ /*
52
+ * The validator compares a raw string so one implementation can serve both
53
+ * services. If either enum ever renames its member, this fails instead of
54
+ * silently skipping sample validation.
55
+ */
56
+ it("matches the literal both action enums use for sampling", () => {
57
+ expect(LogDropFilterAction.Sample).toBe(SAMPLE_ACTION);
58
+ expect(TraceDropFilterAction.Sample).toBe(SAMPLE_ACTION);
59
+ });
60
+ });
61
+
62
+ describe("validateDropFilterFilterQuery", () => {
63
+ it("accepts a query with an actual condition", () => {
64
+ expect(() => {
65
+ return validateDropFilterFilterQuery("body CONTAINS 'debug'", LOGS);
66
+ }).not.toThrow();
67
+ });
68
+
69
+ /*
70
+ * The destructive case: empty means match-all, and match-all plus a drop
71
+ * action means the project loses everything.
72
+ */
73
+ it("rejects an empty query", () => {
74
+ expect(() => {
75
+ return validateDropFilterFilterQuery("", LOGS);
76
+ }).toThrow(BadDataException);
77
+ });
78
+
79
+ it("rejects a whitespace-only query", () => {
80
+ for (const blank of [" ", " ", "\t", "\n", " \t\n "]) {
81
+ expect(() => {
82
+ return validateDropFilterFilterQuery(blank, LOGS);
83
+ }).toThrow(BadDataException);
84
+ }
85
+ });
86
+
87
+ it("rejects a missing query", () => {
88
+ expect(() => {
89
+ return validateDropFilterFilterQuery(undefined, LOGS);
90
+ }).toThrow(BadDataException);
91
+ expect(() => {
92
+ return validateDropFilterFilterQuery(null, LOGS);
93
+ }).toThrow(BadDataException);
94
+ });
95
+
96
+ /*
97
+ * The message has to explain the consequence, not just name the field —
98
+ * "Filter query is required" alone does not tell someone that saving it
99
+ * blank would have deleted all their logs.
100
+ */
101
+ it("explains the consequence in the message, in the caller's vocabulary", () => {
102
+ expect(() => {
103
+ return validateDropFilterFilterQuery("", LOGS);
104
+ }).toThrow(/discard all of this project's logs/);
105
+
106
+ expect(() => {
107
+ return validateDropFilterFilterQuery("", SPANS);
108
+ }).toThrow(/discard all of this project's spans/);
109
+ });
110
+ });
111
+
112
+ describe("validateDropFilterSamplePercentage", () => {
113
+ it("ignores the percentage entirely for a drop-action filter", () => {
114
+ for (const percentage of [null, undefined, 0, -5, 100, 1000]) {
115
+ expect(() => {
116
+ return validateDropFilterSamplePercentage(
117
+ candidate({ action: "drop", samplePercentage: percentage }),
118
+ LOGS,
119
+ );
120
+ }).not.toThrow();
121
+ }
122
+ });
123
+
124
+ it("accepts a sample filter inside the usable range", () => {
125
+ for (const percentage of [
126
+ MIN_SAMPLE_PERCENTAGE,
127
+ 10,
128
+ 50,
129
+ MAX_SAMPLE_PERCENTAGE,
130
+ ]) {
131
+ expect(() => {
132
+ return validateDropFilterSamplePercentage(
133
+ candidate({ action: SAMPLE_ACTION, samplePercentage: percentage }),
134
+ LOGS,
135
+ );
136
+ }).not.toThrow();
137
+ }
138
+ });
139
+
140
+ it("rejects a sample filter with no percentage at all", () => {
141
+ for (const missing of [null, undefined]) {
142
+ expect(() => {
143
+ return validateDropFilterSamplePercentage(
144
+ candidate({ action: SAMPLE_ACTION, samplePercentage: missing }),
145
+ LOGS,
146
+ );
147
+ }).toThrow(BadDataException);
148
+ }
149
+ });
150
+
151
+ it("rejects a sample filter with a non-finite percentage", () => {
152
+ for (const bad of [NaN, Infinity, -Infinity]) {
153
+ expect(() => {
154
+ return validateDropFilterSamplePercentage(
155
+ candidate({ action: SAMPLE_ACTION, samplePercentage: bad }),
156
+ LOGS,
157
+ );
158
+ }).toThrow(BadDataException);
159
+ }
160
+ });
161
+
162
+ /*
163
+ * 0 and 100 are the two values a user reaches for when they mean something
164
+ * else. Point them at the tool that actually does it rather than accepting
165
+ * a filter the engine will treat as a no-op.
166
+ */
167
+ it("rejects 0 and points at the Drop action instead", () => {
168
+ expect(() => {
169
+ return validateDropFilterSamplePercentage(
170
+ candidate({ action: SAMPLE_ACTION, samplePercentage: 0 }),
171
+ LOGS,
172
+ );
173
+ }).toThrow(/"Drop" action/);
174
+ });
175
+
176
+ it("rejects 100 and points at disabling the filter instead", () => {
177
+ expect(() => {
178
+ return validateDropFilterSamplePercentage(
179
+ candidate({ action: SAMPLE_ACTION, samplePercentage: 100 }),
180
+ LOGS,
181
+ );
182
+ }).toThrow(/disable the filter/);
183
+ });
184
+
185
+ it("rejects percentages outside the range on both sides", () => {
186
+ for (const outOfRange of [-1, 0, 100, 101, 1000]) {
187
+ expect(() => {
188
+ return validateDropFilterSamplePercentage(
189
+ candidate({ action: SAMPLE_ACTION, samplePercentage: outOfRange }),
190
+ LOGS,
191
+ );
192
+ }).toThrow(BadDataException);
193
+ }
194
+ });
195
+
196
+ it("names the allowed range in the message so the fix is obvious", () => {
197
+ expect(() => {
198
+ return validateDropFilterSamplePercentage(
199
+ candidate({ action: SAMPLE_ACTION, samplePercentage: null }),
200
+ LOGS,
201
+ );
202
+ }).toThrow(
203
+ new RegExp(`${MIN_SAMPLE_PERCENTAGE} and ${MAX_SAMPLE_PERCENTAGE}`),
204
+ );
205
+ });
206
+ });
207
+
208
+ describe("validateDropFilter", () => {
209
+ it("accepts a well-formed drop filter", () => {
210
+ expect(() => {
211
+ return validateDropFilter(
212
+ candidate({ action: "drop", filterQuery: "severityText = 'Debug'" }),
213
+ LOGS,
214
+ );
215
+ }).not.toThrow();
216
+ });
217
+
218
+ it("accepts a well-formed sample filter", () => {
219
+ expect(() => {
220
+ return validateDropFilter(
221
+ candidate({
222
+ action: SAMPLE_ACTION,
223
+ samplePercentage: 10,
224
+ filterQuery: "severityText = 'Debug'",
225
+ }),
226
+ LOGS,
227
+ );
228
+ }).not.toThrow();
229
+ });
230
+
231
+ /*
232
+ * The query check runs first on purpose. A row that is broken both ways
233
+ * should surface the more destructive problem, because a match-all drop
234
+ * filter deletes everything while a bad percentage only samples.
235
+ */
236
+ it("reports the empty query first when a candidate is broken both ways", () => {
237
+ expect(() => {
238
+ return validateDropFilter(
239
+ candidate({
240
+ action: SAMPLE_ACTION,
241
+ samplePercentage: null,
242
+ filterQuery: "",
243
+ }),
244
+ LOGS,
245
+ );
246
+ }).toThrow(/Filter query is required/);
247
+ });
248
+ });
249
+
250
+ describe("isSqlExpressionValue", () => {
251
+ /*
252
+ * `PartialEntity` values may be raw SQL expressions. We cannot evaluate one
253
+ * to validate it, and stringifying a function to compare it would be worse
254
+ * than skipping — so the update hook detects and skips.
255
+ */
256
+ it("detects a raw SQL expression value", () => {
257
+ expect(
258
+ isSqlExpressionValue(() => {
259
+ return "NOW()";
260
+ }),
261
+ ).toBe(true);
262
+ });
263
+
264
+ it("treats every ordinary literal as a plain value", () => {
265
+ for (const literal of ["sample", "", 0, 50, null, undefined, {}, []]) {
266
+ expect(isSqlExpressionValue(literal)).toBe(false);
267
+ }
268
+ });
269
+ });
@@ -0,0 +1,94 @@
1
+ import SpanUtil, {
2
+ SpanAttributes,
3
+ } from "../../../../Server/Utils/Telemetry/SpanUtil";
4
+ import { describe, expect, it, jest } from "@jest/globals";
5
+
6
+ /*
7
+ * SpanUtil.addAttributesToSpan copies telemetry attributes onto a span, but it
8
+ * must drop undefined/null values - OpenTelemetry rejects those and throwing
9
+ * mid-request would break the traced operation. This pins the filtering so a
10
+ * partially-populated SpanAttributes object stays safe to pass in.
11
+ */
12
+
13
+ // A stand-in Span that just records what setAttribute was called with.
14
+ function fakeSpan(): {
15
+ span: { setAttribute: (key: string, value: unknown) => void };
16
+ calls: Array<[string, unknown]>;
17
+ } {
18
+ const calls: Array<[string, unknown]> = [];
19
+ const setAttribute: (key: string, value: unknown) => void = jest.fn(
20
+ (key: string, value: unknown): void => {
21
+ calls.push([key, value]);
22
+ },
23
+ );
24
+ return { span: { setAttribute }, calls };
25
+ }
26
+
27
+ describe("SpanUtil.addAttributesToSpan", () => {
28
+ it("sets every defined attribute on the span", () => {
29
+ const { span, calls } = fakeSpan();
30
+
31
+ const attributes: SpanAttributes = {
32
+ userId: "user-1",
33
+ projectId: "project-1",
34
+ };
35
+
36
+ SpanUtil.addAttributesToSpan({
37
+ span: span as never,
38
+ attributes,
39
+ });
40
+
41
+ expect(calls).toContainEqual(["userId", "user-1"]);
42
+ expect(calls).toContainEqual(["projectId", "project-1"]);
43
+ expect(calls).toHaveLength(2);
44
+ });
45
+
46
+ it("skips undefined and null values (OpenTelemetry rejects them)", () => {
47
+ const { span, calls } = fakeSpan();
48
+
49
+ const attributes: SpanAttributes = {
50
+ userId: "user-1",
51
+ projectId: undefined,
52
+ // null is not part of the typed surface but can arrive at runtime.
53
+ monitorId: null as unknown as string,
54
+ };
55
+
56
+ SpanUtil.addAttributesToSpan({
57
+ span: span as never,
58
+ attributes,
59
+ });
60
+
61
+ expect(calls).toEqual([["userId", "user-1"]]);
62
+ });
63
+
64
+ it("preserves falsy-but-defined values like empty string, 0 and false", () => {
65
+ const { span, calls } = fakeSpan();
66
+
67
+ const attributes: SpanAttributes = {
68
+ channelId: "",
69
+ retryCount: 0,
70
+ isRetry: false,
71
+ };
72
+
73
+ SpanUtil.addAttributesToSpan({
74
+ span: span as never,
75
+ attributes,
76
+ });
77
+
78
+ expect(calls).toContainEqual(["channelId", ""]);
79
+ expect(calls).toContainEqual(["retryCount", 0]);
80
+ expect(calls).toContainEqual(["isRetry", false]);
81
+ expect(calls).toHaveLength(3);
82
+ });
83
+
84
+ it("does nothing for an empty attribute object", () => {
85
+ const { span, calls } = fakeSpan();
86
+
87
+ SpanUtil.addAttributesToSpan({
88
+ span: span as never,
89
+ attributes: {},
90
+ });
91
+
92
+ expect(calls).toHaveLength(0);
93
+ });
94
+ });
@@ -139,6 +139,58 @@ describe("OneUptimeDate user timezone", () => {
139
139
  expect(formatted).toContain("EDT");
140
140
  });
141
141
 
142
+ it("names the abbreviation in effect on the formatted date, not today's", () => {
143
+ OneUptimeDate.setUserTimezone(NY);
144
+
145
+ /*
146
+ * The abbreviation used to be looked up for "now", so all summer every
147
+ * winter timestamp read "EDT" — and 13:00 EDT is a different instant
148
+ * than the 13:00 EST that was actually stored.
149
+ */
150
+ const winter: string = OneUptimeDate.getDateAsLocalFormattedString(
151
+ new Date("2026-01-15T18:00:00Z"),
152
+ );
153
+ const summer: string = OneUptimeDate.getDateAsLocalFormattedString(
154
+ new Date("2026-07-15T18:00:00Z"),
155
+ );
156
+
157
+ expect(winter).toContain("13:00");
158
+ expect(winter).toContain("EST");
159
+ expect(winter).not.toContain("EDT");
160
+
161
+ expect(summer).toContain("14:00");
162
+ expect(summer).toContain("EDT");
163
+ });
164
+
165
+ it("labels each pass of a folded fall-back hour with its own abbreviation", () => {
166
+ OneUptimeDate.setUserTimezone(NY);
167
+
168
+ // 01:30 local happens twice on 2026-11-01 — once EDT, once EST.
169
+ const firstPass: string = OneUptimeDate.getDateAsLocalFormattedString(
170
+ new Date("2026-11-01T05:30:00Z"),
171
+ );
172
+ const secondPass: string = OneUptimeDate.getDateAsLocalFormattedString(
173
+ new Date("2026-11-01T06:30:00Z"),
174
+ );
175
+
176
+ expect(firstPass).toContain("01:30");
177
+ expect(secondPass).toContain("01:30");
178
+ // Identical wall clocks; the abbreviation is what tells them apart.
179
+ expect(firstPass).toContain("EDT");
180
+ expect(secondPass).toContain("EST");
181
+ });
182
+
183
+ it("still omits the abbreviation when only the date is shown", () => {
184
+ OneUptimeDate.setUserTimezone(NY);
185
+
186
+ const dateOnly: string = OneUptimeDate.getDateAsLocalFormattedString(
187
+ new Date("2026-01-15T18:00:00Z"),
188
+ true,
189
+ );
190
+
191
+ expect(dateOnly).toBe("Jan 15, 2026");
192
+ });
193
+
142
194
  it("reads the hour and minute of an instant in the user timezone", () => {
143
195
  OneUptimeDate.setUserTimezone(KOLKATA);
144
196
 
@@ -1,4 +1,4 @@
1
- import { JSONArray, JSONObject } from "../../Types/JSON";
1
+ import { JSONArray, JSONObject, ObjectType } from "../../Types/JSON";
2
2
  import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
3
3
  import JSONFunctions from "../../Types/JSONFunctions";
4
4
 
@@ -262,4 +262,106 @@ describe("JSONFunctions Class", () => {
262
262
  expect(size).toBeGreaterThanOrEqual(0);
263
263
  });
264
264
  });
265
+
266
+ describe("serialize and serializeArray Methods", () => {
267
+ test("Passes primitives and null through, and drops undefined keys", () => {
268
+ const input: JSONObject = {
269
+ n: 1,
270
+ s: "x",
271
+ b: true,
272
+ nil: null,
273
+ gone: undefined,
274
+ };
275
+ expect(JSONFunctions.serialize(input)).toEqual({
276
+ n: 1,
277
+ s: "x",
278
+ b: true,
279
+ nil: null,
280
+ });
281
+ });
282
+
283
+ test("Tags a Date value with its DateTime object type", () => {
284
+ const serialized: JSONObject = JSONFunctions.serialize({
285
+ when: new Date("2023-01-01T00:00:00.000Z"),
286
+ });
287
+ const when: JSONObject = serialized["when"] as JSONObject;
288
+ expect(when["_type"]).toBe(ObjectType.DateTime);
289
+ expect(typeof when["value"]).toBe("string");
290
+ });
291
+
292
+ test("Serializes nested objects recursively", () => {
293
+ expect(JSONFunctions.serialize({ a: { b: 2 } })).toEqual({ a: { b: 2 } });
294
+ });
295
+
296
+ test("Serializes each value inside an array", () => {
297
+ expect(JSONFunctions.serialize({ arr: [1, "x", null] })).toEqual({
298
+ arr: [1, "x", null],
299
+ });
300
+ });
301
+
302
+ test("serializeArray serializes each object in the array", () => {
303
+ const input: JSONArray = [{ a: 1 }, { b: 2 }];
304
+ expect(JSONFunctions.serializeArray(input)).toEqual([{ a: 1 }, { b: 2 }]);
305
+ });
306
+ });
307
+
308
+ describe("deserialize and deserializeArray Methods", () => {
309
+ test("Passes primitives and null through", () => {
310
+ const input: JSONObject = { n: 1, s: "x", nil: null };
311
+ expect(JSONFunctions.deserialize(input)).toEqual({
312
+ n: 1,
313
+ s: "x",
314
+ nil: null,
315
+ });
316
+ });
317
+
318
+ test("Rebuilds a Buffer-tagged value into a Buffer", () => {
319
+ const input: JSONObject = {
320
+ payload: {
321
+ _type: ObjectType.Buffer,
322
+ value: { type: ObjectType.Buffer, data: [1, 2, 3] },
323
+ },
324
+ };
325
+ const deserialized: JSONObject = JSONFunctions.deserialize(input);
326
+ expect(Buffer.isBuffer(deserialized["payload"])).toBe(true);
327
+ expect(deserialized["payload"]).toEqual(Buffer.from([1, 2, 3]));
328
+ });
329
+
330
+ test("deserializeArray deserializes each object in the array", () => {
331
+ const input: JSONArray = [{ a: 1 }, { b: 2 }];
332
+ expect(JSONFunctions.deserializeArray(input)).toEqual([
333
+ { a: 1 },
334
+ { b: 2 },
335
+ ]);
336
+ });
337
+ });
338
+
339
+ describe("serializeValue and deserializeValue Methods", () => {
340
+ test("Pass numbers and non-empty strings through unchanged", () => {
341
+ expect(JSONFunctions.serializeValue(5)).toBe(5);
342
+ expect(JSONFunctions.serializeValue("hi")).toBe("hi");
343
+ expect(JSONFunctions.deserializeValue(5)).toBe(5);
344
+ expect(JSONFunctions.deserializeValue("hi")).toBe("hi");
345
+ });
346
+
347
+ test("Pass null through unchanged", () => {
348
+ expect(JSONFunctions.serializeValue(null)).toBeNull();
349
+ expect(JSONFunctions.deserializeValue(null)).toBeNull();
350
+ });
351
+ });
352
+
353
+ describe("serialize and deserialize round trip", () => {
354
+ test("A plain object survives a serialize -> JSON -> deserialize round trip", () => {
355
+ const original: JSONObject = {
356
+ a: 1,
357
+ b: "x",
358
+ c: { d: 2 },
359
+ e: [1, 2, 3],
360
+ };
361
+ const roundTripped: JSONObject = JSONFunctions.deserialize(
362
+ JSON.parse(JSON.stringify(JSONFunctions.serialize(original))),
363
+ );
364
+ expect(roundTripped).toEqual(original);
365
+ });
366
+ });
265
367
  });