@oneuptime/common 13.0.8 → 14.0.1

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 (514) hide show
  1. package/Models/AnalyticsModels/AuditLog.ts +23 -15
  2. package/Models/DatabaseModels/GlobalConfig.ts +24 -0
  3. package/Models/DatabaseModels/Index.ts +4 -0
  4. package/Models/DatabaseModels/Monitor.ts +3 -2
  5. package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
  6. package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +2 -0
  7. package/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.ts +522 -0
  8. package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +38 -4
  9. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.ts +603 -0
  10. package/Scripts/generate-service-worker.js +65 -4
  11. package/Server/API/BaseAPI.ts +26 -5
  12. package/Server/API/GlobalConfigAPI.ts +228 -462
  13. package/Server/API/ProjectOIDC.ts +25 -16
  14. package/Server/API/ProjectSSO.ts +24 -16
  15. package/Server/API/StatusPageAPI.ts +100 -42
  16. package/Server/API/TeamMemberAPI.ts +10 -1
  17. package/Server/Enterprise/EnterpriseEdition.ts +649 -0
  18. package/Server/Enterprise/EnterpriseFeature.ts +48 -0
  19. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
  20. package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
  21. package/Server/EnvironmentConfig.ts +147 -2
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.ts +248 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.ts +19 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  26. package/Server/Middleware/UserAuthorization.ts +38 -16
  27. package/Server/Services/AuditLogService.ts +84 -1079
  28. package/Server/Services/DatabaseService.ts +10 -0
  29. package/Server/Services/EnterpriseLicenseService.ts +38 -0
  30. package/Server/Services/GlobalConfigService.ts +80 -1
  31. package/Server/Services/Index.ts +4 -0
  32. package/Server/Services/MonitorProbeService.ts +116 -20
  33. package/Server/Services/MonitorService.ts +59 -6
  34. package/Server/Services/MonitorStatusTimelineService.ts +284 -0
  35. package/Server/Services/MonitorTemplateService.ts +26 -0
  36. package/Server/Services/ProjectService.ts +284 -0
  37. package/Server/Services/RumSessionPinService.ts +25 -6
  38. package/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.ts +385 -0
  39. package/Server/Services/ServiceLevelObjectiveLabelRuleService.ts +51 -0
  40. package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +92 -16
  41. package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +36 -1
  42. package/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.ts +521 -0
  43. package/Server/Services/ServiceLevelObjectiveOwnerRuleService.ts +51 -0
  44. package/Server/Services/ServiceLevelObjectiveService.ts +28 -0
  45. package/Server/Services/StatusPagePrivateUserService.ts +7 -3
  46. package/Server/Services/StatusPageService.ts +78 -1
  47. package/Server/Services/TeamMemberService.ts +11 -0
  48. package/Server/Services/TeamService.ts +10 -0
  49. package/Server/Services/UserService.ts +10 -17
  50. package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
  51. package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
  52. package/Server/Types/Database/Permissions/TablePermission.ts +10 -3
  53. package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
  54. package/Server/Types/Markdown.ts +41 -0
  55. package/Server/Types/Workflow/Components/Telegram/SendMessageToChat.ts +27 -1
  56. package/Server/Utils/AI/Toolbox/SloTools.ts +1 -0
  57. package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
  58. package/Server/Utils/EditionEnforcement.ts +233 -0
  59. package/Server/Utils/FrontendEnvironment.ts +41 -2
  60. package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
  61. package/Server/Utils/Monitor/AffectedResourceList.ts +148 -0
  62. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +1 -1
  63. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
  64. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +1 -1
  65. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +720 -465
  66. package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
  67. package/Server/Utils/Monitor/RootCauseList.ts +139 -0
  68. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +28 -0
  69. package/Server/Utils/Slo/SloRulePatternValidator.ts +42 -0
  70. package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
  71. package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
  72. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
  73. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
  74. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
  75. package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
  76. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
  77. package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
  78. package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
  79. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
  80. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
  81. package/Tests/App/Dashboard/FeedFilterSortIntegration.test.tsx +1632 -0
  82. package/Tests/App/Dashboard/FeedOptionsLocales.test.ts +250 -0
  83. package/Tests/App/Dashboard/FeedOrdering.test.ts +279 -9
  84. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
  85. package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +60 -1
  86. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +594 -3
  87. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
  88. package/Tests/App/Dashboard/ProductOrientation.test.tsx +646 -0
  89. package/Tests/App/Dashboard/ResourceFeed.test.tsx +612 -2
  90. package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +30 -0
  91. package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +1202 -0
  92. package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +52 -1
  93. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +45 -9
  94. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
  95. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
  96. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -83
  97. package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
  98. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
  99. package/Tests/App/Dashboard/SloFeed.test.tsx +106 -1
  100. package/Tests/App/Dashboard/SloMonitorRuleCriteria.test.tsx +566 -0
  101. package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +6 -4
  102. package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +186 -0
  103. package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +388 -44
  104. package/Tests/App/Dashboard/SloOverviewLayout.test.tsx +613 -0
  105. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
  106. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
  107. package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
  108. package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
  109. package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +0 -8
  110. package/Tests/Models/DatabaseModels/SloLabelAndOwnerRuleModels.test.ts +404 -0
  111. package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +17 -1
  112. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  113. package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
  114. package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
  115. package/Tests/Server/API/GlobalConfigLicense.test.ts +742 -497
  116. package/Tests/Server/API/OnCallReadinessAPI.test.ts +35 -909
  117. package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
  118. package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
  119. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
  120. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
  121. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
  122. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
  123. package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
  124. package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
  125. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
  126. package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
  127. package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
  128. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
  129. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
  130. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  131. package/Tests/Server/Infrastructure/Postgres/AddSloLabelAndOwnerRulesMigration.test.ts +407 -0
  132. package/Tests/Server/Infrastructure/Postgres/AddSloMonitorRuleMonitorTypeMigration.test.ts +171 -0
  133. package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +88 -4
  134. package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
  135. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
  136. package/Tests/Server/Services/AuditLogService.test.ts +460 -990
  137. package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
  138. package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +104 -0
  139. package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
  140. package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
  141. package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
  142. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
  143. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
  144. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
  145. package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
  146. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +48 -1
  147. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -0
  148. package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
  149. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +1170 -0
  150. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleServices.test.ts +172 -0
  151. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +323 -0
  152. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +115 -0
  153. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleTriggers.test.ts +21 -2
  154. package/Tests/Server/Services/ServiceLevelObjectiveMonitorTypePostgres.test.ts +480 -0
  155. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +162 -0
  156. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
  157. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
  158. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +45 -6
  159. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
  160. package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
  161. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
  162. package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +745 -0
  163. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
  164. package/Tests/Server/Types/Markdown.test.ts +183 -1
  165. package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +49 -0
  166. package/Tests/Server/Types/Workflow/Components/TelegramSendMessageToChat.test.ts +331 -0
  167. package/Tests/Server/Utils/AI/SloTools.test.ts +10 -0
  168. package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
  169. package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
  170. package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
  171. package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
  172. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
  173. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
  174. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +1 -1
  175. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +1339 -96
  176. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +1101 -0
  177. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +106 -80
  178. package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
  179. package/Tests/Server/Utils/Monitor/RootCauseList.test.ts +252 -0
  180. package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +154 -0
  181. package/Tests/Server/Utils/SSRFProtection.test.ts +111 -0
  182. package/Tests/Server/Utils/Slo/SloRulePatternValidator.test.ts +67 -0
  183. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +213 -0
  184. package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
  185. package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
  186. package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
  187. package/Tests/Types/API/Route.test.ts +56 -0
  188. package/Tests/Types/API/URLSchemeLikePath.test.ts +304 -0
  189. package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
  190. package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
  191. package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
  192. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +84 -178
  193. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
  194. package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
  195. package/Tests/UI/Components/FeedOptions.test.ts +1404 -0
  196. package/Tests/UI/Components/FeedOptionsButton.test.tsx +2603 -0
  197. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
  198. package/Tests/UI/Components/Icon.test.tsx +26 -0
  199. package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
  200. package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
  201. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  202. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
  203. package/Tests/UI/Components/useFeedItemsViewKey.test.tsx +1017 -0
  204. package/Tests/UI/Components/useFeedOptions.test.tsx +1107 -0
  205. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
  206. package/Tests/Utils/HostAddressUtil.test.ts +138 -0
  207. package/Tests/Utils/LabelRuleImportExport.test.ts +102 -0
  208. package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
  209. package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
  210. package/Tests/Utils/Slo/SloDuration.test.ts +115 -24
  211. package/Tests/Utils/Slo/SloHealth.test.ts +93 -10
  212. package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +109 -0
  213. package/Tests/Utils/Slo/SloOverviewText.test.ts +64 -0
  214. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
  215. package/Types/API/Hostname.ts +63 -16
  216. package/Types/API/Route.ts +19 -2
  217. package/Types/API/URL.ts +26 -2
  218. package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
  219. package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
  220. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
  221. package/Types/Database/CanonicalModelInstance.ts +102 -0
  222. package/Types/Database/TableColumn.ts +20 -6
  223. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
  224. package/Types/IP/IPv6.ts +6 -1
  225. package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +6 -5
  226. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +9 -0
  227. package/Types/Monitor/MonitorStep.ts +6 -1
  228. package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
  229. package/Types/Permission.ts +90 -0
  230. package/Types/Rules/RuleCriteriaFieldRegistry.ts +11 -0
  231. package/Types/Rules/RuleRun.ts +4 -0
  232. package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
  233. package/UI/Components/EditionLabel/EditionLabel.tsx +796 -1195
  234. package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
  235. package/UI/Components/Feed/FeedOptions.ts +427 -0
  236. package/UI/Components/Feed/FeedOptionsButton.tsx +692 -0
  237. package/UI/Components/Feed/useFeedItems.ts +28 -9
  238. package/UI/Components/Feed/useFeedOptions.ts +225 -0
  239. package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
  240. package/UI/Components/Icon/Icon.tsx +1 -1
  241. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  242. package/UI/Components/ModelList/ModelList.tsx +11 -1
  243. package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
  244. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
  245. package/UI/esbuild-enterprise.js +263 -0
  246. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
  247. package/Utils/HostAddressUtil.ts +94 -0
  248. package/Utils/LabelRuleImportExport.ts +27 -9
  249. package/Utils/Monitor/MetricValueFormatter.ts +2 -2
  250. package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
  251. package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
  252. package/Utils/Rules/MonitorTypeRuleCriteria.ts +31 -0
  253. package/Utils/Slo/SloDuration.ts +22 -6
  254. package/Utils/Slo/SloHealth.ts +8 -7
  255. package/Utils/Slo/SloMonitorRuleCriteria.ts +33 -1
  256. package/Utils/Slo/SloOverviewText.ts +33 -0
  257. package/Utils/Slo/SloProjection.ts +4 -3
  258. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
  259. package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
  260. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  261. package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
  262. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  263. package/build/dist/Models/DatabaseModels/Index.js +4 -0
  264. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  265. package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
  266. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  267. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
  268. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  269. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +2 -0
  270. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -1
  271. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js +530 -0
  272. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js.map +1 -0
  273. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +39 -4
  274. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -1
  275. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js +612 -0
  276. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js.map +1 -0
  277. package/build/dist/Server/API/BaseAPI.js +26 -5
  278. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  279. package/build/dist/Server/API/GlobalConfigAPI.js +148 -344
  280. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  281. package/build/dist/Server/API/ProjectOIDC.js +24 -16
  282. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  283. package/build/dist/Server/API/ProjectSSO.js +24 -16
  284. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  285. package/build/dist/Server/API/StatusPageAPI.js +93 -43
  286. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  287. package/build/dist/Server/API/TeamMemberAPI.js +8 -1
  288. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  289. package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
  290. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
  291. package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
  292. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
  293. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
  294. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
  295. package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
  296. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
  297. package/build/dist/Server/EnvironmentConfig.js +84 -2
  298. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  299. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
  300. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
  301. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js +93 -0
  302. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js.map +1 -0
  303. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js +12 -0
  304. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js.map +1 -0
  305. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  306. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  307. package/build/dist/Server/Middleware/UserAuthorization.js +30 -11
  308. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  309. package/build/dist/Server/Services/AuditLogService.js +71 -740
  310. package/build/dist/Server/Services/AuditLogService.js.map +1 -1
  311. package/build/dist/Server/Services/DatabaseService.js +7 -0
  312. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  313. package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
  314. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  315. package/build/dist/Server/Services/GlobalConfigService.js +63 -0
  316. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  317. package/build/dist/Server/Services/Index.js +4 -0
  318. package/build/dist/Server/Services/Index.js.map +1 -1
  319. package/build/dist/Server/Services/MonitorProbeService.js +90 -17
  320. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  321. package/build/dist/Server/Services/MonitorService.js +48 -6
  322. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  323. package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
  324. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  325. package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
  326. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  327. package/build/dist/Server/Services/ProjectService.js +214 -0
  328. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  329. package/build/dist/Server/Services/RumSessionPinService.js +24 -6
  330. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  331. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js +295 -0
  332. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js.map +1 -0
  333. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js +56 -0
  334. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js.map +1 -0
  335. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +59 -14
  336. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
  337. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +22 -1
  338. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -1
  339. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js +400 -0
  340. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js.map +1 -0
  341. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js +56 -0
  342. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js.map +1 -0
  343. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +21 -0
  344. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
  345. package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
  346. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  347. package/build/dist/Server/Services/StatusPageService.js +71 -0
  348. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  349. package/build/dist/Server/Services/TeamMemberService.js +10 -0
  350. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  351. package/build/dist/Server/Services/TeamService.js +9 -0
  352. package/build/dist/Server/Services/TeamService.js.map +1 -1
  353. package/build/dist/Server/Services/UserService.js +10 -16
  354. package/build/dist/Server/Services/UserService.js.map +1 -1
  355. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
  356. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  357. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
  358. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  359. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +10 -3
  360. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  361. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
  362. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  363. package/build/dist/Server/Types/Markdown.js +31 -0
  364. package/build/dist/Server/Types/Markdown.js.map +1 -1
  365. package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js +20 -1
  366. package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js.map +1 -1
  367. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +1 -0
  368. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
  369. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
  370. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
  371. package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
  372. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
  373. package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
  374. package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
  375. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
  376. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
  377. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +67 -0
  378. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
  379. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +1 -1
  380. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  381. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  382. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +1 -1
  383. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +585 -367
  384. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  385. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
  386. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
  387. package/build/dist/Server/Utils/Monitor/RootCauseList.js +101 -0
  388. package/build/dist/Server/Utils/Monitor/RootCauseList.js.map +1 -0
  389. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +28 -0
  390. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  391. package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js +28 -0
  392. package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js.map +1 -0
  393. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
  394. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  395. package/build/dist/Types/API/Hostname.js +59 -11
  396. package/build/dist/Types/API/Hostname.js.map +1 -1
  397. package/build/dist/Types/API/Route.js +18 -2
  398. package/build/dist/Types/API/Route.js.map +1 -1
  399. package/build/dist/Types/API/URL.js +23 -2
  400. package/build/dist/Types/API/URL.js.map +1 -1
  401. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
  402. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
  403. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
  404. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
  405. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
  406. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
  407. package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
  408. package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
  409. package/build/dist/Types/Database/TableColumn.js +19 -6
  410. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  411. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
  412. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
  413. package/build/dist/Types/IP/IPv6.js +6 -1
  414. package/build/dist/Types/IP/IPv6.js.map +1 -1
  415. package/build/dist/Types/Monitor/MonitorStep.js +5 -0
  416. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  417. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
  418. package/build/dist/Types/Permission.js +84 -0
  419. package/build/dist/Types/Permission.js.map +1 -1
  420. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +11 -0
  421. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  422. package/build/dist/Types/Rules/RuleRun.js +4 -0
  423. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  424. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
  425. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
  426. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +414 -585
  427. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  428. package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
  429. package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
  430. package/build/dist/UI/Components/Feed/FeedOptions.js +235 -0
  431. package/build/dist/UI/Components/Feed/FeedOptions.js.map +1 -0
  432. package/build/dist/UI/Components/Feed/FeedOptionsButton.js +346 -0
  433. package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -0
  434. package/build/dist/UI/Components/Feed/useFeedItems.js +17 -7
  435. package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -1
  436. package/build/dist/UI/Components/Feed/useFeedOptions.js +130 -0
  437. package/build/dist/UI/Components/Feed/useFeedOptions.js.map +1 -0
  438. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
  439. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  440. package/build/dist/UI/Components/Icon/Icon.js +1 -1
  441. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  442. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  443. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  444. package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
  445. package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
  446. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
  447. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  448. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
  449. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  450. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
  451. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  452. package/build/dist/Utils/HostAddressUtil.js +80 -0
  453. package/build/dist/Utils/HostAddressUtil.js.map +1 -0
  454. package/build/dist/Utils/LabelRuleImportExport.js +22 -6
  455. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  456. package/build/dist/Utils/Monitor/MetricValueFormatter.js +2 -2
  457. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
  458. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
  459. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
  460. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
  461. package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js +18 -0
  462. package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js.map +1 -0
  463. package/build/dist/Utils/Slo/SloDuration.js +13 -5
  464. package/build/dist/Utils/Slo/SloDuration.js.map +1 -1
  465. package/build/dist/Utils/Slo/SloHealth.js +8 -7
  466. package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
  467. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +16 -1
  468. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -1
  469. package/build/dist/Utils/Slo/SloOverviewText.js +16 -0
  470. package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -1
  471. package/build/dist/Utils/Slo/SloProjection.js.map +1 -1
  472. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  473. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
  474. package/jest.config.json +3 -1
  475. package/package.json +1 -1
  476. package/test-setup.sh +103 -34
  477. package/tsconfig.json +13 -0
  478. package/Server/API/EnterpriseLicenseAPI.ts +0 -925
  479. package/Server/API/TeamComplianceAPI.ts +0 -158
  480. package/Server/Middleware/SCIMAuthorization.ts +0 -141
  481. package/Server/Services/TeamComplianceService.ts +0 -733
  482. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
  483. package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
  484. package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
  485. package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
  486. package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +0 -761
  487. package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
  488. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
  489. package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +0 -321
  490. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
  491. package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
  492. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
  493. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
  494. package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
  495. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
  496. package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
  497. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
  498. package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
  499. package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
  500. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
  501. package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
  502. package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
  503. package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
  504. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
  505. package/build/dist/Server/Services/TeamComplianceService.js +0 -537
  506. package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
  507. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
  508. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
  509. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
  510. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
  511. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
  512. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
  513. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
  514. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
@@ -0,0 +1,250 @@
1
+ import {
2
+ FEED_OPTIONS_TEXT,
3
+ FEED_SORT_ORDER_OPTIONS,
4
+ FILTERED_FEED_NO_ITEMS_MESSAGE,
5
+ FeedSortOrderOption,
6
+ getFeedEventTypeLabel,
7
+ } from "../../../UI/Components/Feed/FeedOptions";
8
+ import {
9
+ DEFAULT_DASHBOARD_LANGUAGE,
10
+ SUPPORTED_DASHBOARD_LANGUAGE_CODES,
11
+ } from "../../../Types/Dashboard/DashboardLanguage";
12
+ import { describe, expect, test } from "@jest/globals";
13
+ import fs from "fs";
14
+ import path from "path";
15
+
16
+ /*
17
+ * The "Filter & Sort" control on every dashboard activity feed looks each of
18
+ * its strings up in the Dashboard locale files by its English text - its own
19
+ * sentences, the two sort choices, the filtered empty state, and the label of
20
+ * every event type in the checklist. A string with no entry silently stays
21
+ * English, and a translation that drops or renames a {{placeholder}} shows a
22
+ * raw brace or a missing number. This pins the English keys to what the code
23
+ * renders and every other language to having a usable translation of each.
24
+ *
25
+ * The event types are discovered from the feed models on disk, not listed
26
+ * here, so a feed model or event type added later needs its label translated
27
+ * before this passes.
28
+ */
29
+
30
+ const COMMON_ROOT: string = path.resolve(__dirname, "..", "..", "..");
31
+
32
+ const MODELS_DIRECTORY: string = path.join(
33
+ COMMON_ROOT,
34
+ "Models",
35
+ "DatabaseModels",
36
+ );
37
+
38
+ const DASHBOARD_LOCALES: string = path.join(
39
+ COMMON_ROOT,
40
+ "..",
41
+ "App",
42
+ "FeatureSet",
43
+ "Dashboard",
44
+ "src",
45
+ "Locales",
46
+ );
47
+
48
+ // The sentence the trigger used as its accessible name before it was retired.
49
+ const RETIRED_KEY: string = "Filter and sort feed: {{summary}}";
50
+
51
+ const FEED_EVENT_TYPE_ENUM_PATTERN: RegExp =
52
+ /export enum (\w+FeedEventType)\b/g;
53
+
54
+ const PLACEHOLDER_PATTERN: RegExp = /\{\{\s*([A-Za-z0-9_]+)\s*\}\}/g;
55
+
56
+ interface FeedEventTypeEnum {
57
+ model: string;
58
+ enumName: string;
59
+ values: Array<string>;
60
+ }
61
+
62
+ type FindFeedEventTypeEnums = () => Array<FeedEventTypeEnum>;
63
+
64
+ /*
65
+ * Every *FeedEventType enum under Models/DatabaseModels, with the values the
66
+ * model module actually exports (loaded, not parsed, so a value written in an
67
+ * unusual way cannot be misread).
68
+ */
69
+ const findFeedEventTypeEnums: FindFeedEventTypeEnums =
70
+ (): Array<FeedEventTypeEnum> => {
71
+ const found: Array<FeedEventTypeEnum> = [];
72
+
73
+ for (const entry of fs.readdirSync(MODELS_DIRECTORY, {
74
+ withFileTypes: true,
75
+ })) {
76
+ if (!entry.isFile() || !entry.name.endsWith(".ts")) {
77
+ continue;
78
+ }
79
+
80
+ const source: string = fs.readFileSync(
81
+ path.join(MODELS_DIRECTORY, entry.name),
82
+ "utf8",
83
+ );
84
+ const enumNames: Array<string> = Array.from(
85
+ source.matchAll(FEED_EVENT_TYPE_ENUM_PATTERN),
86
+ (match: RegExpMatchArray): string => {
87
+ return match[1]!;
88
+ },
89
+ );
90
+
91
+ if (enumNames.length === 0) {
92
+ continue;
93
+ }
94
+
95
+ const model: string = entry.name.replace(/\.ts$/, "");
96
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
97
+ const exported: Record<string, unknown> = require(
98
+ path.join(MODELS_DIRECTORY, model),
99
+ );
100
+
101
+ for (const enumName of enumNames) {
102
+ const eventTypeEnum: unknown = exported[enumName];
103
+
104
+ found.push({
105
+ model,
106
+ enumName,
107
+ values:
108
+ eventTypeEnum && typeof eventTypeEnum === "object"
109
+ ? Object.values(eventTypeEnum as Record<string, string>)
110
+ : [],
111
+ });
112
+ }
113
+ }
114
+
115
+ return found;
116
+ };
117
+
118
+ type ReadLocale = (fileName: string) => Record<string, unknown>;
119
+
120
+ const readLocale: ReadLocale = (fileName: string): Record<string, unknown> => {
121
+ return JSON.parse(
122
+ fs.readFileSync(path.join(DASHBOARD_LOCALES, fileName), "utf8"),
123
+ ) as Record<string, unknown>;
124
+ };
125
+
126
+ type GetPlaceholders = (text: string) => Array<string>;
127
+
128
+ // The placeholder names in a string, repeats kept, in a stable order.
129
+ const getPlaceholders: GetPlaceholders = (text: string): Array<string> => {
130
+ return Array.from(
131
+ text.matchAll(PLACEHOLDER_PATTERN),
132
+ (match: RegExpMatchArray): string => {
133
+ return match[1]!;
134
+ },
135
+ ).sort();
136
+ };
137
+
138
+ type Unique = (values: Array<string>) => Array<string>;
139
+
140
+ const unique: Unique = (values: Array<string>): Array<string> => {
141
+ return Array.from(new Set<string>(values));
142
+ };
143
+
144
+ const FEED_EVENT_TYPE_ENUMS: Array<FeedEventTypeEnum> =
145
+ findFeedEventTypeEnums();
146
+
147
+ // The control's own words, exactly as it passes them to the translator.
148
+ const CONTROL_KEYS: Array<string> = unique([
149
+ ...Object.values(FEED_OPTIONS_TEXT),
150
+ ...FEED_SORT_ORDER_OPTIONS.map((option: FeedSortOrderOption): string => {
151
+ return option.label;
152
+ }),
153
+ FILTERED_FEED_NO_ITEMS_MESSAGE,
154
+ ]);
155
+
156
+ // The checklist's labels, which are translated by their English text too.
157
+ const EVENT_TYPE_LABEL_KEYS: Array<string> = unique(
158
+ FEED_EVENT_TYPE_ENUMS.flatMap((eventTypeEnum: FeedEventTypeEnum) => {
159
+ return eventTypeEnum.values.map((value: string): string => {
160
+ return getFeedEventTypeLabel(value);
161
+ });
162
+ }),
163
+ );
164
+
165
+ const ALL_KEYS: Array<string> = unique([
166
+ ...CONTROL_KEYS,
167
+ ...EVENT_TYPE_LABEL_KEYS,
168
+ ]);
169
+
170
+ const OTHER_LANGUAGES: Array<string> =
171
+ SUPPORTED_DASHBOARD_LANGUAGE_CODES.filter((code: string): boolean => {
172
+ return code !== DEFAULT_DASHBOARD_LANGUAGE;
173
+ });
174
+
175
+ describe("Filter & Sort translations in the Dashboard locales", () => {
176
+ test("the feed models on disk were found and loaded", () => {
177
+ // An empty or unloaded scan would make every check below vacuous.
178
+ expect(FEED_EVENT_TYPE_ENUMS.length).toBeGreaterThan(0);
179
+
180
+ for (const eventTypeEnum of FEED_EVENT_TYPE_ENUMS) {
181
+ expect({
182
+ enumName: eventTypeEnum.enumName,
183
+ loaded: eventTypeEnum.values.length > 0,
184
+ }).toEqual({ enumName: eventTypeEnum.enumName, loaded: true });
185
+ }
186
+
187
+ expect(OTHER_LANGUAGES.length).toBeGreaterThan(0);
188
+ });
189
+
190
+ test("English maps every string the control shows to itself", () => {
191
+ const english: Record<string, unknown> = readLocale(
192
+ `${DEFAULT_DASHBOARD_LANGUAGE}.json`,
193
+ );
194
+
195
+ const missing: Array<string> = ALL_KEYS.filter((key: string): boolean => {
196
+ return english[key] !== key;
197
+ });
198
+
199
+ expect(missing).toEqual([]);
200
+ });
201
+
202
+ test.each(OTHER_LANGUAGES)(
203
+ "%s translates every string the control shows, keeping its placeholders",
204
+ (language: string) => {
205
+ const locale: Record<string, unknown> = readLocale(`${language}.json`);
206
+ const problems: Array<string> = [];
207
+
208
+ for (const key of ALL_KEYS) {
209
+ const value: unknown = locale[key];
210
+
211
+ if (typeof value !== "string" || value.trim().length === 0) {
212
+ problems.push(`missing: ${key}`);
213
+ continue;
214
+ }
215
+
216
+ const expected: string = getPlaceholders(key).join(",");
217
+ const actual: string = getPlaceholders(value).join(",");
218
+
219
+ if (actual !== expected) {
220
+ problems.push(
221
+ `placeholders {${actual}} instead of {${expected}}: ${key}`,
222
+ );
223
+ }
224
+ }
225
+
226
+ expect(problems).toEqual([]);
227
+ },
228
+ );
229
+
230
+ test("the retired accessible-name sentence is in no locale file", () => {
231
+ const localeFiles: Array<string> = fs
232
+ .readdirSync(DASHBOARD_LOCALES)
233
+ .filter((fileName: string): boolean => {
234
+ return fileName.endsWith(".json");
235
+ });
236
+
237
+ expect(localeFiles.length).toBeGreaterThan(1);
238
+
239
+ const stillThere: Array<string> = localeFiles.filter(
240
+ (fileName: string): boolean => {
241
+ return Object.prototype.hasOwnProperty.call(
242
+ readLocale(fileName),
243
+ RETIRED_KEY,
244
+ );
245
+ },
246
+ );
247
+
248
+ expect(stillThere).toEqual([]);
249
+ });
250
+ });
@@ -7,6 +7,22 @@ interface FeedImplementation {
7
7
  relativePath: string;
8
8
  }
9
9
 
10
+ /*
11
+ * How one feed connects its Filter & Sort state to the request it makes. The
12
+ * checks below compare against the name the feed itself gave the
13
+ * useFeedOptions() result, and look inside the two hook calls rather than
14
+ * the whole file, so they survive renames and reformatting but not a wire
15
+ * that goes to the wrong place.
16
+ */
17
+ interface FeedOptionsWiring {
18
+ // What the feed called its useFeedOptions() result.
19
+ hook: string;
20
+ // The arguments of the useFeedOptions() call.
21
+ optionsCall: string;
22
+ // The arguments of the useFeedItems() call: the request the feed makes.
23
+ itemsCall: string;
24
+ }
25
+
10
26
  const DASHBOARD_COMPONENTS: string = path.join(
11
27
  __dirname,
12
28
  "..",
@@ -62,14 +78,30 @@ const FEED_IMPLEMENTATIONS: Array<FeedImplementation> = [
62
78
  },
63
79
  ];
64
80
 
65
- function readSource(implementation: FeedImplementation): string {
81
+ /*
82
+ * Ends at the call's opening parenthesis, so the same pattern both names the
83
+ * result and locates the call's arguments.
84
+ */
85
+ const FEED_OPTIONS_HOOK_CALL: RegExp =
86
+ /const\s+(\w+)\s*:\s*UseFeedOptionsResult\s*=\s*useFeedOptions\s*\(/;
87
+
88
+ const FEED_ITEMS_HOOK_CALL: RegExp = /\buseFeedItems\s*(?:<[^<>()]*>)?\s*\(/;
89
+
90
+ // A storage key written as a string literal ("incident"), not an expression.
91
+ const QUOTED_STRING_LITERAL: RegExp = /^(["'`])[^"'`]*\1$/;
92
+
93
+ const readSource: (implementation: FeedImplementation) => string = (
94
+ implementation: FeedImplementation,
95
+ ): string => {
66
96
  return fs.readFileSync(
67
97
  path.join(DASHBOARD_COMPONENTS, implementation.relativePath),
68
98
  "utf8",
69
99
  );
70
- }
100
+ };
71
101
 
72
- function findFeedImplementationPaths(directory: string): Array<string> {
102
+ const findFeedImplementationPaths: (directory: string) => Array<string> = (
103
+ directory: string,
104
+ ): Array<string> => {
73
105
  return fs
74
106
  .readdirSync(directory, { withFileTypes: true })
75
107
  .flatMap((entry: fs.Dirent): Array<string> => {
@@ -95,7 +127,104 @@ function findFeedImplementationPaths(directory: string): Array<string> {
95
127
  .join("/"),
96
128
  ];
97
129
  });
98
- }
130
+ };
131
+
132
+ /*
133
+ * The text between the parentheses of the first call that `callee` finds (a
134
+ * pattern ending at the opening parenthesis). Strings and comments are
135
+ * skipped, so a bracket inside one cannot end the call early.
136
+ */
137
+ const getCallArguments: (source: string, callee: RegExp) => string = (
138
+ source: string,
139
+ callee: RegExp,
140
+ ): string => {
141
+ const match: RegExpExecArray | null = callee.exec(source);
142
+
143
+ if (!match) {
144
+ throw new Error(`No call matching ${callee.toString()}`);
145
+ }
146
+
147
+ const openIndex: number = match.index + match[0].length - 1;
148
+ let depth: number = 0;
149
+ let index: number = openIndex;
150
+
151
+ while (index < source.length) {
152
+ const character: string = source[index]!;
153
+ const nextCharacter: string | undefined = source[index + 1];
154
+
155
+ if (character === "/" && nextCharacter === "*") {
156
+ index = source.indexOf("*/", index + 2) + 2;
157
+ continue;
158
+ }
159
+
160
+ if (character === "/" && nextCharacter === "/") {
161
+ const lineEnd: number = source.indexOf("\n", index);
162
+ index = lineEnd === -1 ? source.length : lineEnd;
163
+ continue;
164
+ }
165
+
166
+ if (character === '"' || character === "'" || character === "`") {
167
+ index++;
168
+
169
+ while (index < source.length && source[index] !== character) {
170
+ index += source[index] === "\\" ? 2 : 1;
171
+ }
172
+
173
+ index++;
174
+ continue;
175
+ }
176
+
177
+ if ("([{".includes(character)) {
178
+ depth++;
179
+ } else if (")]}".includes(character)) {
180
+ depth--;
181
+
182
+ if (depth === 0) {
183
+ return source.slice(openIndex + 1, index);
184
+ }
185
+ }
186
+
187
+ index++;
188
+ }
189
+
190
+ throw new Error(`Unbalanced call matching ${callee.toString()}`);
191
+ };
192
+
193
+ /*
194
+ * A property's value expression inside a call's arguments, with whitespace
195
+ * removed so that line breaks never decide whether two expressions match.
196
+ */
197
+ const getPropertyExpression: (
198
+ callArguments: string,
199
+ property: string,
200
+ ) => string | undefined = (
201
+ callArguments: string,
202
+ property: string,
203
+ ): string | undefined => {
204
+ const match: RegExpMatchArray | null = callArguments.match(
205
+ new RegExp(String.raw`\b${property}\s*:\s*([^,}]+?)\s*[,}]`),
206
+ );
207
+
208
+ return match ? match[1]!.replace(/\s+/g, "") : undefined;
209
+ };
210
+
211
+ const getFeedOptionsWiring: (source: string) => FeedOptionsWiring = (
212
+ source: string,
213
+ ): FeedOptionsWiring => {
214
+ const hookMatch: RegExpMatchArray | null = source.match(
215
+ FEED_OPTIONS_HOOK_CALL,
216
+ );
217
+
218
+ if (!hookMatch) {
219
+ throw new Error("The feed does not keep a UseFeedOptionsResult");
220
+ }
221
+
222
+ return {
223
+ hook: hookMatch[1]!,
224
+ optionsCall: getCallArguments(source, FEED_OPTIONS_HOOK_CALL),
225
+ itemsCall: getCallArguments(source, FEED_ITEMS_HOOK_CALL),
226
+ };
227
+ };
99
228
 
100
229
  describe("dashboard feed ordering parity", () => {
101
230
  test("tracks every feed implementation", () => {
@@ -110,20 +239,161 @@ describe("dashboard feed ordering parity", () => {
110
239
  );
111
240
  });
112
241
 
242
+ /*
243
+ * The order is the reader's choice from the Filter & Sort button, and it
244
+ * is applied by the API. Reversing or re-sorting the loaded window in the
245
+ * browser would show the newest ten upside down instead of the oldest ten.
246
+ */
113
247
  test.each(FEED_IMPLEMENTATIONS)(
114
- "$name requests the newest activity first",
248
+ "$name requests activity in the reader's chosen order",
115
249
  (implementation: FeedImplementation) => {
116
250
  const source: string = readSource(implementation);
251
+ const wiring: FeedOptionsWiring = getFeedOptionsWiring(source);
117
252
 
118
- expect(source).toContain("postedAt: SortOrder.Descending");
119
- expect(source).not.toContain("postedAt: SortOrder.Ascending");
253
+ expect(wiring.itemsCall).toMatch(
254
+ new RegExp(
255
+ String.raw`\bpostedAt\s*:\s*${wiring.hook}\.options\.sortOrder\b`,
256
+ ),
257
+ );
258
+ expect(source).not.toMatch(/\bpostedAt\s*:\s*SortOrder\./);
120
259
  expect(source).not.toContain(".reverse()");
121
- expect(source).toContain("skip: 0");
122
- expect(source).toContain("limit,");
260
+ expect(wiring.itemsCall).toMatch(/\bskip\s*:\s*0\b/);
261
+ expect(wiring.itemsCall).toMatch(/\blimit\s*,/);
123
262
  expect(source).not.toContain("LIMIT_PER_PROJECT");
124
263
  },
125
264
  );
126
265
 
266
+ test.each(FEED_IMPLEMENTATIONS)(
267
+ "$name offers Filter & Sort as the first header control and filters through the API",
268
+ (implementation: FeedImplementation) => {
269
+ const source: string = readSource(implementation);
270
+ const wiring: FeedOptionsWiring = getFeedOptionsWiring(source);
271
+ const hook: string = wiring.hook;
272
+
273
+ expect(source).toMatch(
274
+ /import\s+useFeedOptions\b[^;]*from\s+"Common\/UI\/Components\/Feed\/useFeedOptions"/,
275
+ );
276
+ expect(source).toMatch(
277
+ /import\s+FeedOptionsButton\s+from\s+"Common\/UI\/Components\/Feed\/FeedOptionsButton"/,
278
+ );
279
+ expect(source).toMatch(/buttons=\{\[\s*<FeedOptionsButton\b/);
280
+
281
+ /*
282
+ * A change of options must both re-read the feed (viewKey) and change
283
+ * what is read (the event type query). Either one alone shows stale or
284
+ * mislabelled items.
285
+ */
286
+ expect(wiring.itemsCall).toMatch(
287
+ new RegExp(String.raw`\bviewKey\s*:\s*${hook}\.optionsKey\b`),
288
+ );
289
+ /*
290
+ * The first argument may carry a generic cast with a comma of its own:
291
+ * ResourceFeed names its column `as Extract<keyof TFeedModel, string>`.
292
+ */
293
+ expect(wiring.itemsCall).toMatch(
294
+ new RegExp(
295
+ String.raw`\.\.\.getFeedEventTypeQuery<\w+>\(\s*(?:[^,()<>]|<[^<>]*>)+,\s*${hook}\.options\s*,?\s*\)`,
296
+ ),
297
+ );
298
+
299
+ const button: RegExpMatchArray | null = source.match(
300
+ /<FeedOptionsButton\b[\s\S]*?\/>/,
301
+ );
302
+
303
+ expect(button).not.toBeNull();
304
+ expect(button![0]).toMatch(
305
+ new RegExp(String.raw`\bvalue=\{\s*${hook}\.options\s*\}`),
306
+ );
307
+ expect(button![0]).toMatch(
308
+ new RegExp(
309
+ String.raw`\beventTypeOptions=\{\s*${hook}\.eventTypeOptions\s*\}`,
310
+ ),
311
+ );
312
+ expect(button![0]).toMatch(
313
+ new RegExp(String.raw`\bonChange=\{\s*${hook}\.setOptions\s*\}`),
314
+ );
315
+
316
+ /*
317
+ * A filtered feed with no matches must say it is filtered, not claim
318
+ * the resource has no activity at all.
319
+ */
320
+ expect(
321
+ getCallArguments(
322
+ source,
323
+ /noItemsMessage=\{\s*getFeedNoItemsMessage\s*\(/,
324
+ ),
325
+ ).toMatch(new RegExp(String.raw`\boptions\s*:\s*${hook}\.options\b`));
326
+ },
327
+ );
328
+
329
+ /*
330
+ * The dashboard moves from one incident (cluster, monitor, ...) to the next
331
+ * without remounting the feed. useFeedItems starts over when its
332
+ * resourceKey changes, and useFeedOptions drops the event type filter when
333
+ * its resetKey changes. Only when both are the same expression do the two
334
+ * happen in the same render, so the first request for the new resource is
335
+ * unfiltered instead of carrying the filter chosen on the previous one.
336
+ */
337
+ test.each(FEED_IMPLEMENTATIONS)(
338
+ "$name drops its event type filter on the render that moves it to another resource",
339
+ (implementation: FeedImplementation) => {
340
+ const wiring: FeedOptionsWiring = getFeedOptionsWiring(
341
+ readSource(implementation),
342
+ );
343
+ const resourceKey: string | undefined = getPropertyExpression(
344
+ wiring.itemsCall,
345
+ "resourceKey",
346
+ );
347
+
348
+ expect(resourceKey).toBeTruthy();
349
+ expect(getPropertyExpression(wiring.optionsCall, "resetKey")).toBe(
350
+ resourceKey,
351
+ );
352
+ },
353
+ );
354
+
355
+ /*
356
+ * Only literal keys can be compared here. ResourceFeed keys its order by
357
+ * props.eventTypeColumn, one per product, and
358
+ * ResourceFeedPagesFilterSort.test.tsx checks that those are distinct.
359
+ */
360
+ test("each feed remembers its sort order under its own storage key", () => {
361
+ const storageKeys: Array<[string, string | undefined]> =
362
+ FEED_IMPLEMENTATIONS.map(
363
+ (implementation: FeedImplementation): [string, string | undefined] => {
364
+ return [
365
+ implementation.name,
366
+ getPropertyExpression(
367
+ getFeedOptionsWiring(readSource(implementation)).optionsCall,
368
+ "storageKey",
369
+ ),
370
+ ];
371
+ },
372
+ );
373
+
374
+ // Without a key the order is forgotten on every page load.
375
+ expect(
376
+ storageKeys
377
+ .filter((entry: [string, string | undefined]): boolean => {
378
+ return !entry[1];
379
+ })
380
+ .map((entry: [string, string | undefined]): string => {
381
+ return entry[0];
382
+ }),
383
+ ).toEqual([]);
384
+
385
+ const literalKeys: Array<string> = storageKeys
386
+ .map((entry: [string, string | undefined]): string => {
387
+ return entry[1] || "";
388
+ })
389
+ .filter((key: string): boolean => {
390
+ return QUOTED_STRING_LITERAL.test(key);
391
+ });
392
+
393
+ expect(literalKeys.length).toBeGreaterThan(1);
394
+ expect(new Set(literalKeys).size).toBe(literalKeys.length);
395
+ });
396
+
127
397
  test.each(FEED_IMPLEMENTATIONS)(
128
398
  "$name uses the shared progressive feed UI",
129
399
  (implementation: FeedImplementation) => {