@oneuptime/common 11.7.4 → 12.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 (896) hide show
  1. package/Models/AnalyticsModels/ExceptionInstance.ts +67 -0
  2. package/Models/AnalyticsModels/Index.ts +10 -0
  3. package/Models/AnalyticsModels/Log.ts +60 -0
  4. package/Models/AnalyticsModels/RumSession.ts +1401 -0
  5. package/Models/AnalyticsModels/RumSessionChunk.ts +798 -0
  6. package/Models/AnalyticsModels/Span.ts +60 -0
  7. package/Models/DatabaseModels/AIAgentTaskPullRequest.ts +52 -0
  8. package/Models/DatabaseModels/AIRun.ts +31 -0
  9. package/Models/DatabaseModels/Alert.ts +29 -0
  10. package/Models/DatabaseModels/AlertCustomField.ts +1 -1
  11. package/Models/DatabaseModels/AlertFeed.ts +1 -0
  12. package/Models/DatabaseModels/AutoRemediationRule.ts +989 -0
  13. package/Models/DatabaseModels/AutoRemediationSuggestion.ts +874 -0
  14. package/Models/DatabaseModels/CodeRepository.ts +129 -0
  15. package/Models/DatabaseModels/GlobalConfig.ts +312 -0
  16. package/Models/DatabaseModels/Incident.ts +29 -0
  17. package/Models/DatabaseModels/IncidentCustomField.ts +1 -1
  18. package/Models/DatabaseModels/IncidentFeed.ts +1 -0
  19. package/Models/DatabaseModels/Index.ts +21 -8
  20. package/Models/DatabaseModels/InstanceHealthLog.ts +8 -0
  21. package/Models/DatabaseModels/MonitorCustomField.ts +1 -1
  22. package/Models/DatabaseModels/MonitorStatus.ts +1 -1
  23. package/Models/DatabaseModels/NetworkDeviceLabelRule.ts +2 -2
  24. package/Models/DatabaseModels/NetworkDeviceOwnerRule.ts +2 -2
  25. package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +1 -1
  26. package/Models/DatabaseModels/OnCallDutyPolicyCustomField.ts +1 -1
  27. package/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.ts +12 -2
  28. package/Models/DatabaseModels/Project.ts +231 -0
  29. package/Models/DatabaseModels/RumApplication.ts +906 -0
  30. package/Models/DatabaseModels/RumSessionErasureRequest.ts +561 -0
  31. package/Models/DatabaseModels/RumSessionPin.ts +457 -0
  32. package/Models/DatabaseModels/RumSessionReplayView.ts +406 -0
  33. package/Models/DatabaseModels/RunbookCredential.ts +673 -0
  34. package/Models/DatabaseModels/RunbookSecret.ts +7 -7
  35. package/Models/DatabaseModels/{RunbookAgent.ts → Runner.ts} +206 -46
  36. package/Models/DatabaseModels/{RunbookAgentJob.ts → RunnerJob.ts} +151 -18
  37. package/Models/DatabaseModels/{RunbookAgentOwnerTeam.ts → RunnerOwnerTeam.ts} +41 -43
  38. package/Models/DatabaseModels/{RunbookAgentOwnerUser.ts → RunnerOwnerUser.ts} +41 -43
  39. package/Models/DatabaseModels/ScheduledMaintenanceCustomField.ts +1 -1
  40. package/Models/DatabaseModels/StatusPageCustomField.ts +1 -1
  41. package/Models/DatabaseModels/TeamCustomField.ts +1 -1
  42. package/Models/DatabaseModels/TeamMemberCustomField.ts +1 -1
  43. package/Server/API/AIAgentDataAPI.ts +179 -48
  44. package/Server/API/AIAgentTaskAPI.ts +36 -37
  45. package/Server/API/AIAgentTaskLogAPI.ts +19 -33
  46. package/Server/API/AutoRemediationAPI.ts +557 -0
  47. package/Server/API/BaseAnalyticsAPI.ts +4 -1
  48. package/Server/API/CommonAPI.ts +35 -0
  49. package/Server/API/DashboardAPI.ts +340 -15
  50. package/Server/API/TelemetryAPI.ts +1622 -3
  51. package/Server/API/UserIncomingCallNumberAPI.ts +31 -0
  52. package/Server/DatabaseConfig.ts +26 -1
  53. package/Server/EnvironmentConfig.ts +13 -0
  54. package/Server/Infrastructure/Postgres/LocalMigrationGenerationDataSource.ts +12 -2
  55. package/Server/Infrastructure/Postgres/SchemaMigrations/1785417351021-AddSessionReplay.ts +293 -0
  56. package/Server/Infrastructure/Postgres/SchemaMigrations/1785491583874-EnableSessionReplayByDefault.ts +67 -0
  57. package/Server/Infrastructure/Postgres/SchemaMigrations/1785496223183-AddMonitorSummaryToIncidentAndAlert.ts +33 -0
  58. package/Server/Infrastructure/Postgres/SchemaMigrations/1785516996695-AddSessionReplayReliabilityColumns.ts +40 -0
  59. package/Server/Infrastructure/Postgres/SchemaMigrations/1785533806494-AddSessionReplayCorrelationColumns.ts +54 -0
  60. package/Server/Infrastructure/Postgres/SchemaMigrations/1785749674203-AddRedisAndPostgresHealthNotificationColumns.ts +104 -0
  61. package/Server/Infrastructure/Postgres/SchemaMigrations/1785763818197-AddAutoRemediation.ts +349 -0
  62. package/Server/Infrastructure/Postgres/SchemaMigrations/1785768089408-AddRemediationVerification.ts +67 -0
  63. package/Server/Infrastructure/Postgres/SchemaMigrations/1785776960660-AddRunnerCapabilities.ts +23 -0
  64. package/Server/Infrastructure/Postgres/SchemaMigrations/1785790000000-AddIncidentInvestigationGating.ts +42 -0
  65. package/Server/Infrastructure/Postgres/SchemaMigrations/1785800000000-AddRunbookCredential.ts +84 -0
  66. package/Server/Infrastructure/Postgres/SchemaMigrations/1785810000000-RenameRunbookAgentToRunner.ts +152 -0
  67. package/Server/Infrastructure/Postgres/SchemaMigrations/1785860000000-SessionReplayDefaultToSensitiveInputMasking.ts +81 -0
  68. package/Server/Infrastructure/Postgres/SchemaMigrations/1785870000000-AddAiCommandRemediation.ts +151 -0
  69. package/Server/Infrastructure/Postgres/SchemaMigrations/1785880000000-AlignRunnerSchemaWithEntities.ts +597 -0
  70. package/Server/Infrastructure/Postgres/SchemaMigrations/1785890000000-AddFixVerificationAndAutomaticCodeFixes.ts +71 -0
  71. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +32 -0
  72. package/Server/Services/AIRunService.ts +10 -0
  73. package/Server/Services/AIService.ts +30 -0
  74. package/Server/Services/AlertService.ts +41 -4
  75. package/Server/Services/AlertSeverityService.ts +25 -11
  76. package/Server/Services/AlertStateService.ts +25 -11
  77. package/Server/Services/AutoRemediationRuleEngineService.ts +1101 -0
  78. package/Server/Services/{RunbookAgentOwnerTeamService.ts → AutoRemediationRuleService.ts} +1 -1
  79. package/Server/Services/AutoRemediationSuggestionService.ts +183 -0
  80. package/Server/Services/BillingService.ts +50 -1
  81. package/Server/Services/DatabaseService.ts +92 -4
  82. package/Server/Services/IncidentService.ts +56 -4
  83. package/Server/Services/IncidentSeverityService.ts +25 -11
  84. package/Server/Services/IncidentStateService.ts +25 -11
  85. package/Server/Services/Index.ts +19 -0
  86. package/Server/Services/LlmProviderService.ts +69 -9
  87. package/Server/Services/MonitorService.ts +24 -0
  88. package/Server/Services/MonitorStatusService.ts +25 -11
  89. package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +18 -19
  90. package/Server/Services/NetworkDeviceLabelRuleService.ts +39 -0
  91. package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +18 -19
  92. package/Server/Services/NetworkDeviceOwnerRuleService.ts +37 -0
  93. package/Server/Services/NetworkDeviceService.ts +172 -21
  94. package/Server/Services/NetworkSiteAssignmentRuleService.ts +92 -12
  95. package/Server/Services/NetworkSiteService.ts +27 -10
  96. package/Server/Services/ProjectService.ts +47 -0
  97. package/Server/Services/RumApplicationService.ts +240 -1
  98. package/Server/Services/RumSessionChunkService.ts +11 -0
  99. package/Server/Services/RumSessionErasureRequestService.ts +197 -0
  100. package/Server/Services/RumSessionPinService.ts +213 -0
  101. package/Server/Services/RumSessionReplayViewService.ts +201 -0
  102. package/Server/Services/RumSessionService.ts +123 -0
  103. package/Server/Services/RunbookCredentialService.ts +76 -0
  104. package/Server/Services/{RunbookAgentJobService.ts → RunnerJobService.ts} +202 -51
  105. package/Server/Services/{RunbookAgentOwnerUserService.ts → RunnerOwnerTeamService.ts} +1 -1
  106. package/Server/Services/RunnerOwnerUserService.ts +10 -0
  107. package/Server/Services/RunnerService.ts +166 -0
  108. package/Server/Services/ScheduledMaintenanceStateService.ts +25 -11
  109. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +15 -1
  110. package/Server/Services/ServiceService.ts +8 -2
  111. package/Server/Services/StatusPageService.ts +240 -36
  112. package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +20 -1
  113. package/Server/Services/TelemetryExceptionService.ts +3 -16
  114. package/Server/Services/TelemetryUsageBillingService.ts +33 -2
  115. package/Server/Services/TraceAggregationService.ts +196 -32
  116. package/Server/Types/Billing/MeteredPlan/AllMeteredPlans.ts +17 -0
  117. package/Server/Types/Billing/MeteredPlan/ServerMeteredPlan.ts +10 -0
  118. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +63 -7
  119. package/Server/Utils/AI/CodeFix/CodeFixAgentAuth.ts +128 -0
  120. package/Server/Utils/AI/CodeFix/CodeFixAgentAvailability.ts +54 -0
  121. package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +17 -10
  122. package/Server/Utils/AI/CodeFix/CodeFixRunQueue.ts +8 -6
  123. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +943 -0
  124. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +866 -0
  125. package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +823 -0
  126. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +103 -12
  127. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +75 -17
  128. package/Server/Utils/AI/SRE/ConfidenceSignal.ts +28 -6
  129. package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +202 -12
  130. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +264 -14
  131. package/Server/Utils/AI/SRE/Insights/Triage.ts +2 -7
  132. package/Server/Utils/AI/SRE/InvestigationGrader.ts +5 -24
  133. package/Server/Utils/AI/SRE/InvestigationQueue.ts +259 -20
  134. package/Server/Utils/AI/SRE/PostedRootCause.ts +82 -0
  135. package/Server/Utils/AI/SRE/README.md +3 -2
  136. package/Server/Utils/AI/SRE/RemediationHandoff.ts +82 -0
  137. package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +6 -19
  138. package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +2 -2
  139. package/Server/Utils/Alert/AlertPrivacyFilter.ts +58 -0
  140. package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +604 -0
  141. package/Server/Utils/AutoRemediation/RemediationVerifier.ts +619 -0
  142. package/Server/Utils/CorsOptions.ts +52 -0
  143. package/Server/Utils/Database/RelationIdUtil.ts +68 -0
  144. package/Server/Utils/Incident/IncidentPrivacyFilter.ts +60 -0
  145. package/Server/Utils/InstanceHealth/PostgresHealth.ts +286 -0
  146. package/Server/Utils/InstanceHealth/RedisHealth.ts +434 -0
  147. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +12 -0
  148. package/Server/Utils/Monitor/MonitorAlert.ts +20 -0
  149. package/Server/Utils/Monitor/MonitorIncident.ts +20 -0
  150. package/Server/Utils/Monitor/MonitorResource.ts +19 -0
  151. package/Server/Utils/Monitor/MonitorSummaryCapture.ts +104 -0
  152. package/Server/Utils/NetworkDevice/RulePatternValidator.ts +44 -0
  153. package/Server/Utils/OpenAPI.ts +2 -1
  154. package/Server/Utils/Runbook/RunbookExecutePermission.ts +94 -0
  155. package/Server/Utils/SessionReplay/SessionReplayErasureTombstone.ts +128 -0
  156. package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +586 -0
  157. package/Server/Utils/SessionReplay/SessionReplayGateCacheStore.ts +188 -0
  158. package/Server/Utils/SessionReplay/SessionReplayReadService.ts +1449 -0
  159. package/Server/Utils/SessionReplay/SessionReplayRetention.ts +114 -0
  160. package/Server/Utils/SessionReplay/SessionReplayTargeting.ts +144 -0
  161. package/Server/Utils/SessionReplay/SessionReplayUsage.ts +92 -0
  162. package/Server/Utils/StartServer.ts +47 -3
  163. package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +44 -10
  164. package/Tests/App/Dashboard/AddWidgetModal.test.tsx +557 -0
  165. package/Tests/App/Dashboard/RunnerInstallInstructions.test.tsx +119 -0
  166. package/Tests/App/Dashboard/RunnerStatus.test.tsx +274 -0
  167. package/Tests/App/Dashboard/WidgetCatalog.test.ts +479 -0
  168. package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +343 -0
  169. package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +320 -0
  170. package/Tests/Models/AnalyticsModels/RumSessionSchema.test.ts +455 -0
  171. package/Tests/Models/AnalyticsModels/SessionIdCorrelation.test.ts +158 -0
  172. package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +447 -0
  173. package/Tests/Models/RunnerVersionLabel.test.ts +223 -0
  174. package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +1287 -0
  175. package/Tests/Server/API/LegacyRunbookAgentRoutes.test.ts +117 -0
  176. package/Tests/Server/API/SessionReplayAPI.test.ts +2093 -0
  177. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +429 -0
  178. package/Tests/Server/API/UserSmsApi.test.ts +68 -2
  179. package/Tests/Server/DatabaseConfig.test.ts +150 -0
  180. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +2 -2
  181. package/Tests/Server/Infrastructure/ProcessSignalDelivery.test.ts +2 -3
  182. package/Tests/Server/Services/AIRunCodeFixClaimScoping.test.ts +100 -0
  183. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +8 -0
  184. package/Tests/Server/Services/AutoRemediationCommandRuleEngine.test.ts +334 -0
  185. package/Tests/Server/Services/AutoRemediationRuleEngineService.test.ts +517 -0
  186. package/Tests/Server/Services/BillingService.test.ts +158 -1
  187. package/Tests/Server/Services/DatabaseServiceEmptyUpdate.test.ts +24 -2
  188. package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +17 -10
  189. package/Tests/Server/Services/DatabaseServiceUpdateColumnsWithoutHooks.test.ts +128 -0
  190. package/Tests/Server/Services/DatabaseServiceUpdateWriteRouting.test.ts +178 -0
  191. package/Tests/Server/Services/DatabaseServiceUpdateWriteRoutingMonitor.test.ts +206 -0
  192. package/Tests/Server/Services/LlmProviderUsableByProject.test.ts +293 -0
  193. package/Tests/Server/Services/MonitorServiceOperationalStatusSelection.test.ts +145 -0
  194. package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +726 -0
  195. package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +570 -9
  196. package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +94 -1
  197. package/Tests/Server/Services/NetworkSiteService.test.ts +85 -0
  198. package/Tests/Server/Services/RumApplicationReplayHealth.test.ts +114 -0
  199. package/Tests/Server/Services/RunbookCredentialService.test.ts +657 -0
  200. package/Tests/Server/Services/SessionReplayCreatePath.test.ts +376 -0
  201. package/Tests/Server/Services/SessionReplayGateCacheInvalidation.test.ts +211 -0
  202. package/Tests/Server/Services/SessionReplayMetering.test.ts +174 -0
  203. package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +555 -0
  204. package/Tests/Server/Services/TelemetryExceptionAIFixReadiness.test.ts +25 -4
  205. package/Tests/Server/Services/TelemetryExceptionCodeFixRun.test.ts +17 -2
  206. package/Tests/Server/Services/TraceAggregationService.test.ts +48 -0
  207. package/Tests/Server/Services/TraceAnalyticsResourceDisplayNames.test.ts +855 -0
  208. package/Tests/Server/Services/UpdateOneByIdKeepsRowId.test.ts +38 -27
  209. package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +44 -0
  210. package/Tests/Server/Utils/AI/AIIncidentGating.test.ts +475 -0
  211. package/Tests/Server/Utils/AI/CodeFix/CodeFixAgentAuth.test.ts +257 -0
  212. package/Tests/Server/Utils/AI/CodeFix/CodeFixAgentAvailability.test.ts +236 -0
  213. package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +44 -6
  214. package/Tests/Server/Utils/AI/CodeFixRunQueue.test.ts +47 -1
  215. package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +2 -2
  216. package/Tests/Server/Utils/AI/FixFromIncidentAutoTrigger.test.ts +294 -0
  217. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +2 -2
  218. package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +47 -3
  219. package/Tests/Server/Utils/AI/InvestigationQueueRemediationExecution.test.ts +233 -0
  220. package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +463 -0
  221. package/Tests/Server/Utils/AI/PostedRootCause.test.ts +254 -0
  222. package/Tests/Server/Utils/AI/RemediationAllowlistNormalization.test.ts +248 -0
  223. package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +1008 -0
  224. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +887 -0
  225. package/Tests/Server/Utils/AI/RemediationHandoff.test.ts +306 -0
  226. package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +745 -0
  227. package/Tests/Server/Utils/AI/SubjectCodeFixRunDedupe.test.ts +291 -0
  228. package/Tests/Server/Utils/AI/ToolArgsExtractors.test.ts +141 -0
  229. package/Tests/Server/Utils/AI/Toolbox/WidgetBuilder.test.ts +205 -0
  230. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +1050 -0
  231. package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +350 -0
  232. package/Tests/Server/Utils/AutoRemediation/RemediationVerifier.test.ts +341 -0
  233. package/Tests/Server/Utils/CorsOptions.test.ts +119 -0
  234. package/Tests/Server/Utils/Database/RelationIdUtil.test.ts +120 -0
  235. package/Tests/Server/Utils/Database/ResolveReferenceId.test.ts +60 -0
  236. package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +337 -0
  237. package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +671 -0
  238. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteria.test.ts +897 -0
  239. package/Tests/Server/Utils/Monitor/MonitorSummaryCapture.test.ts +205 -0
  240. package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +313 -0
  241. package/Tests/Server/Utils/PushNotificationUtil.test.ts +228 -0
  242. package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +177 -0
  243. package/Tests/Server/Utils/SessionReplay/SessionReplayOriginAllowlist.test.ts +108 -0
  244. package/Tests/Server/Utils/SessionReplay/SessionReplayRetention.test.ts +229 -0
  245. package/Tests/Server/Utils/SessionReplay/SessionReplayTargeting.test.ts +246 -0
  246. package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +110 -0
  247. package/Tests/Types/AI/AIRunStatus.test.ts +25 -0
  248. package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +1063 -0
  249. package/Tests/Types/BaseDatabase/AggregationType.test.ts +56 -0
  250. package/Tests/Types/CustomField/CustomFieldDropdownOption.test.ts +227 -0
  251. package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +811 -0
  252. package/Tests/Types/Dashboard/RumDashboardTemplate.test.ts +1238 -0
  253. package/Tests/Types/Day/DayOfWeek.test.ts +46 -0
  254. package/Tests/Types/Docker/DockerInventoryExtractor.test.ts +249 -0
  255. package/Tests/Types/Kubernetes/KubernetesInventoryExtractor.test.ts +231 -0
  256. package/Tests/Types/Kubernetes/KubernetesRightSizing.test.ts +323 -0
  257. package/Tests/Types/Metrics/MetricDownsamplingRetentionDays.test.ts +77 -0
  258. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +42 -14
  259. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +2 -2
  260. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +3 -2
  261. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +1 -1
  262. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +6 -3
  263. package/Tests/Types/Monitor/RumAlertTemplates.test.ts +285 -0
  264. package/Tests/Types/Podman/PodmanInventoryExtractor.test.ts +159 -0
  265. package/Tests/Types/Runbook/RunbookExecutionDeadline.test.ts +268 -0
  266. package/Tests/Types/Runbook/RunbookStepType.test.ts +242 -0
  267. package/Tests/Types/Runner/RunnerLiveStatus.test.ts +320 -0
  268. package/Tests/Types/Telemetry/TelemetryRetentionConfig.test.ts +225 -0
  269. package/Tests/Types/Text.test.ts +60 -0
  270. package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +285 -0
  271. package/Tests/UI/Components/AutocompleteTextInputMenu.test.tsx +555 -0
  272. package/Tests/UI/Components/BulkLabelActions.test.tsx +1502 -0
  273. package/Tests/UI/Components/BulkOwnerActions.test.tsx +1255 -0
  274. package/Tests/UI/Components/CustomFields/DropdownOptionsInput.test.tsx +228 -0
  275. package/Tests/UI/Components/Detail/DropdownColors.test.tsx +128 -0
  276. package/Tests/UI/Components/Detail/EntityFields.test.tsx +166 -0
  277. package/Tests/UI/Components/Dropdown/DropdownValueBadge.test.tsx +60 -0
  278. package/Tests/UI/Components/FilterModalOperatorMenu.test.tsx +674 -0
  279. package/Tests/UI/Components/Forms/ColorPicker.test.tsx +48 -0
  280. package/Tests/UI/Components/Forms/ColorPickerPopup.test.tsx +222 -0
  281. package/Tests/UI/Components/Forms/IconPickerPopup.test.tsx +270 -0
  282. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +125 -6
  283. package/Tests/UI/Components/OperatorSelectorFilterTypes.test.tsx +1595 -0
  284. package/Tests/UI/Components/OperatorSelectorKeyboard.test.tsx +851 -0
  285. package/Tests/UI/Components/OperatorSelectorMenu.test.tsx +1229 -0
  286. package/Tests/UI/Components/Pagination.test.tsx +85 -0
  287. package/Tests/UI/Monitor/MonitorSummarySnapshotRender.test.tsx +248 -0
  288. package/Tests/UI/Rum/ChunkLoader.test.ts +790 -0
  289. package/Tests/UI/Rum/ReplayScrubber.test.tsx +236 -0
  290. package/Tests/UI/Rum/ReplayStage.test.tsx +606 -0
  291. package/Tests/UI/Utils/Timezone.test.ts +86 -0
  292. package/Tests/UI/Utils/UseClockTick.test.tsx +276 -0
  293. package/Tests/Utils/AiRemediation/CommandPolicy.test.ts +1063 -0
  294. package/Tests/Utils/Dashboard/ClockWidgetFormat.test.ts +1374 -0
  295. package/Tests/Utils/Dashboard/DashboardClockComponent.test.ts +362 -0
  296. package/Tests/Utils/Dashboard/DashboardHtmlComponent.test.ts +217 -0
  297. package/Tests/Utils/Dashboard/HtmlWidgetDocument.test.ts +656 -0
  298. package/Tests/Utils/Dashboard/ValueWidgetLayout.test.ts +1007 -0
  299. package/Tests/Utils/Metrics/MetricSeriesScope.test.ts +1197 -0
  300. package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +839 -0
  301. package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +69 -0
  302. package/Tests/Utils/Rules/RulePatternMatchUtil.test.ts +274 -0
  303. package/Tests/Utils/Rum/ChunkMath.test.ts +286 -0
  304. package/Tests/Utils/Rum/Masking.test.ts +186 -0
  305. package/Tests/Utils/Rum/SessionIdentity.test.ts +272 -0
  306. package/Tests/Utils/Rum/SessionSampling.test.ts +164 -0
  307. package/Tests/Utils/Rum/UrlScrubber.test.ts +175 -0
  308. package/Tests/Utils/StatusPage/Report.test.ts +708 -0
  309. package/Tests/Utils/ValueFormatter.test.ts +299 -1
  310. package/Types/AI/AIRunStatus.ts +18 -7
  311. package/Types/AI/AIRunType.ts +18 -0
  312. package/Types/AI/FixVerificationStatus.ts +21 -0
  313. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +16 -0
  314. package/Types/AutoRemediation/AiRemediationCommandPlan.ts +304 -0
  315. package/Types/AutoRemediation/AutoRemediationExecutionMode.ts +17 -0
  316. package/Types/AutoRemediation/AutoRemediationSuggestionStatus.ts +35 -0
  317. package/Types/AutoRemediation/AutoRemediationSuggestionType.ts +17 -0
  318. package/Types/AutoRemediation/AutoRemediationTriggerEntity.ts +11 -0
  319. package/Types/AutoRemediation/AutoRemediationVerificationStatus.ts +21 -0
  320. package/Types/CustomField/CustomFieldDropdownOption.ts +190 -0
  321. package/Types/Dashboard/DashboardComponentType.ts +2 -0
  322. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +4 -0
  323. package/Types/Dashboard/DashboardComponents/DashboardClockComponent.ts +45 -0
  324. package/Types/Dashboard/DashboardComponents/DashboardHtmlComponent.ts +27 -0
  325. package/Types/Dashboard/DashboardComponents/DashboardValueComponent.ts +8 -0
  326. package/Types/Dashboard/DashboardTemplates.ts +516 -0
  327. package/Types/Date.ts +6 -0
  328. package/Types/Email/EmailTemplateType.ts +2 -0
  329. package/Types/Kubernetes/KubernetesRightSizing.ts +353 -0
  330. package/Types/MeteredPlan/ProductType.ts +1 -0
  331. package/Types/Monitor/MonitorStepMetricMonitor.ts +27 -1
  332. package/Types/Monitor/MonitorSteps.ts +5 -0
  333. package/Types/Monitor/MonitorSummarySnapshot.ts +88 -0
  334. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +52 -10
  335. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +7 -5
  336. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +101 -20
  337. package/Types/Monitor/RumAlertTemplates.ts +386 -0
  338. package/Types/Permission.ts +204 -24
  339. package/Types/Rum/SessionReplay.ts +452 -0
  340. package/Types/Rum/SessionReplayCaptureTrigger.ts +26 -0
  341. package/Types/Rum/SessionReplayConsentMode.ts +27 -0
  342. package/Types/Rum/SessionReplayMaskingMode.ts +86 -0
  343. package/Types/Rum/SessionReplayTriggerReason.ts +31 -0
  344. package/Types/Runbook/RunbookCredentialType.ts +6 -0
  345. package/Types/Runbook/RunbookStep.ts +81 -1
  346. package/Types/Runbook/RunbookStepType.ts +26 -0
  347. package/Types/Runbook/RunnerJobOrigin.ts +20 -0
  348. package/Types/Runbook/{RunbookAgentJobStatus.ts → RunnerJobStatus.ts} +2 -2
  349. package/Types/Runner/RunnerLiveStatus.ts +114 -0
  350. package/Types/StatusPage/StatusPageReport.ts +99 -0
  351. package/Types/Telemetry/TelemetryRetentionConfig.ts +18 -1
  352. package/Types/Text.ts +33 -0
  353. package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +260 -75
  354. package/UI/Components/BulkUpdate/BulkLabelActions.tsx +99 -9
  355. package/UI/Components/BulkUpdate/BulkOwnerActions.tsx +11 -0
  356. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +19 -14
  357. package/UI/Components/CustomFields/DropdownOptionsInput.tsx +144 -54
  358. package/UI/Components/Detail/Detail.tsx +164 -22
  359. package/UI/Components/Dropdown/Dropdown.tsx +2 -5
  360. package/UI/Components/Dropdown/DropdownMenuZIndex.ts +7 -0
  361. package/UI/Components/Dropdown/DropdownValueBadge.tsx +61 -0
  362. package/UI/Components/Filters/OperatorSelector.tsx +350 -39
  363. package/UI/Components/Forms/Fields/ColorPicker.tsx +60 -27
  364. package/UI/Components/Forms/Fields/IconPicker.tsx +89 -60
  365. package/UI/Components/Forms/Validation.ts +9 -4
  366. package/UI/Components/List/List.tsx +1 -0
  367. package/UI/Components/ModelTable/CustomFieldColumns.tsx +41 -32
  368. package/UI/Components/Pagination/Pagination.tsx +33 -10
  369. package/UI/Components/Table/Table.tsx +1 -0
  370. package/UI/Types/UseAnchoredFieldPopup.ts +321 -0
  371. package/UI/Utils/Dropdown.ts +26 -0
  372. package/UI/Utils/Timezone.ts +18 -2
  373. package/UI/Utils/UseClockTick.ts +78 -0
  374. package/Utils/AiRemediation/CommandPolicy.ts +398 -0
  375. package/Utils/Dashboard/ClockWidgetFormat.ts +604 -0
  376. package/Utils/Dashboard/Components/DashboardClockComponent.ts +181 -0
  377. package/Utils/Dashboard/Components/DashboardHtmlComponent.ts +162 -0
  378. package/Utils/Dashboard/Components/DashboardValueComponent.ts +12 -1
  379. package/Utils/Dashboard/Components/Index.ts +14 -0
  380. package/Utils/Dashboard/HtmlWidgetDocument.ts +309 -0
  381. package/Utils/Dashboard/ValueWidgetLayout.ts +471 -0
  382. package/Utils/Metrics/MetricSeriesScope.ts +301 -0
  383. package/Utils/Monitor/MonitorSummarySnapshotUtil.ts +593 -0
  384. package/Utils/NetworkSite/CidrMatchUtil.ts +30 -17
  385. package/Utils/Rules/RulePatternMatchUtil.ts +103 -0
  386. package/Utils/Rum/ChunkMath.ts +211 -0
  387. package/Utils/Rum/Masking.ts +168 -0
  388. package/Utils/Rum/SessionIdentity.ts +230 -0
  389. package/Utils/Rum/SessionSampling.ts +108 -0
  390. package/Utils/Rum/UrlScrubber.ts +185 -0
  391. package/Utils/Schema/ModelSchema.ts +27 -3
  392. package/Utils/StatusPage/Report.ts +304 -0
  393. package/Utils/ValueFormatter.ts +300 -54
  394. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js +63 -0
  395. package/build/dist/Models/AnalyticsModels/ExceptionInstance.js.map +1 -1
  396. package/build/dist/Models/AnalyticsModels/Index.js +10 -0
  397. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  398. package/build/dist/Models/AnalyticsModels/Log.js +56 -0
  399. package/build/dist/Models/AnalyticsModels/Log.js.map +1 -1
  400. package/build/dist/Models/AnalyticsModels/RumSession.js +1159 -0
  401. package/build/dist/Models/AnalyticsModels/RumSession.js.map +1 -0
  402. package/build/dist/Models/AnalyticsModels/RumSessionChunk.js +670 -0
  403. package/build/dist/Models/AnalyticsModels/RumSessionChunk.js.map +1 -0
  404. package/build/dist/Models/AnalyticsModels/Span.js +56 -0
  405. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  406. package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js +54 -0
  407. package/build/dist/Models/DatabaseModels/AIAgentTaskPullRequest.js.map +1 -1
  408. package/build/dist/Models/DatabaseModels/AIRun.js +32 -0
  409. package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
  410. package/build/dist/Models/DatabaseModels/Alert.js +30 -0
  411. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  412. package/build/dist/Models/DatabaseModels/AlertCustomField.js +1 -1
  413. package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -1
  414. package/build/dist/Models/DatabaseModels/AlertFeed.js +1 -0
  415. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  416. package/build/dist/Models/DatabaseModels/AutoRemediationRule.js +998 -0
  417. package/build/dist/Models/DatabaseModels/AutoRemediationRule.js.map +1 -0
  418. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +917 -0
  419. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -0
  420. package/build/dist/Models/DatabaseModels/CodeRepository.js +132 -0
  421. package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
  422. package/build/dist/Models/DatabaseModels/GlobalConfig.js +327 -0
  423. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  424. package/build/dist/Models/DatabaseModels/Incident.js +30 -0
  425. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  426. package/build/dist/Models/DatabaseModels/IncidentCustomField.js +1 -1
  427. package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
  428. package/build/dist/Models/DatabaseModels/IncidentFeed.js +1 -0
  429. package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
  430. package/build/dist/Models/DatabaseModels/Index.js +20 -8
  431. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  432. package/build/dist/Models/DatabaseModels/InstanceHealthLog.js +8 -0
  433. package/build/dist/Models/DatabaseModels/InstanceHealthLog.js.map +1 -1
  434. package/build/dist/Models/DatabaseModels/MonitorCustomField.js +1 -1
  435. package/build/dist/Models/DatabaseModels/MonitorCustomField.js.map +1 -1
  436. package/build/dist/Models/DatabaseModels/MonitorStatus.js +1 -1
  437. package/build/dist/Models/DatabaseModels/MonitorStatus.js.map +1 -1
  438. package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js +2 -2
  439. package/build/dist/Models/DatabaseModels/NetworkDeviceLabelRule.js.map +1 -1
  440. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js +2 -2
  441. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerRule.js.map +1 -1
  442. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +1 -1
  443. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -1
  444. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js +1 -1
  445. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js.map +1 -1
  446. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js +16 -4
  447. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js.map +1 -1
  448. package/build/dist/Models/DatabaseModels/Project.js +235 -0
  449. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  450. package/build/dist/Models/DatabaseModels/RumApplication.js +930 -0
  451. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  452. package/build/dist/Models/DatabaseModels/RumSessionErasureRequest.js +591 -0
  453. package/build/dist/Models/DatabaseModels/RumSessionErasureRequest.js.map +1 -0
  454. package/build/dist/Models/DatabaseModels/RumSessionPin.js +483 -0
  455. package/build/dist/Models/DatabaseModels/RumSessionPin.js.map +1 -0
  456. package/build/dist/Models/DatabaseModels/RumSessionReplayView.js +433 -0
  457. package/build/dist/Models/DatabaseModels/RumSessionReplayView.js.map +1 -0
  458. package/build/dist/Models/DatabaseModels/RunbookCredential.js +693 -0
  459. package/build/dist/Models/DatabaseModels/RunbookCredential.js.map +1 -0
  460. package/build/dist/Models/DatabaseModels/RunbookSecret.js +8 -8
  461. package/build/dist/Models/DatabaseModels/RunbookSecret.js.map +1 -1
  462. package/build/dist/Models/DatabaseModels/{RunbookAgent.js → Runner.js} +235 -70
  463. package/build/dist/Models/DatabaseModels/Runner.js.map +1 -0
  464. package/build/dist/Models/DatabaseModels/{RunbookAgentJob.js → RunnerJob.js} +173 -40
  465. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -0
  466. package/build/dist/Models/DatabaseModels/{RunbookAgentOwnerTeam.js → RunnerOwnerTeam.js} +57 -57
  467. package/build/dist/Models/DatabaseModels/RunnerOwnerTeam.js.map +1 -0
  468. package/build/dist/Models/DatabaseModels/{RunbookAgentOwnerUser.js → RunnerOwnerUser.js} +57 -57
  469. package/build/dist/Models/DatabaseModels/RunnerOwnerUser.js.map +1 -0
  470. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js +1 -1
  471. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js.map +1 -1
  472. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js +1 -1
  473. package/build/dist/Models/DatabaseModels/StatusPageCustomField.js.map +1 -1
  474. package/build/dist/Models/DatabaseModels/TeamCustomField.js +1 -1
  475. package/build/dist/Models/DatabaseModels/TeamCustomField.js.map +1 -1
  476. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js +1 -1
  477. package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js.map +1 -1
  478. package/build/dist/Server/API/AIAgentDataAPI.js +130 -45
  479. package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
  480. package/build/dist/Server/API/AIAgentTaskAPI.js +26 -36
  481. package/build/dist/Server/API/AIAgentTaskAPI.js.map +1 -1
  482. package/build/dist/Server/API/AIAgentTaskLogAPI.js +11 -28
  483. package/build/dist/Server/API/AIAgentTaskLogAPI.js.map +1 -1
  484. package/build/dist/Server/API/AutoRemediationAPI.js +416 -0
  485. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -0
  486. package/build/dist/Server/API/BaseAnalyticsAPI.js +4 -1
  487. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  488. package/build/dist/Server/API/CommonAPI.js +24 -0
  489. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  490. package/build/dist/Server/API/DashboardAPI.js +265 -6
  491. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  492. package/build/dist/Server/API/TelemetryAPI.js +940 -3
  493. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  494. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +18 -0
  495. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  496. package/build/dist/Server/DatabaseConfig.js +23 -4
  497. package/build/dist/Server/DatabaseConfig.js.map +1 -1
  498. package/build/dist/Server/EnvironmentConfig.js +8 -0
  499. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  500. package/build/dist/Server/Infrastructure/Postgres/LocalMigrationGenerationDataSource.js +11 -1
  501. package/build/dist/Server/Infrastructure/Postgres/LocalMigrationGenerationDataSource.js.map +1 -1
  502. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785417351021-AddSessionReplay.js +106 -0
  503. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785417351021-AddSessionReplay.js.map +1 -0
  504. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785491583874-EnableSessionReplayByDefault.js +37 -0
  505. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785491583874-EnableSessionReplayByDefault.js.map +1 -0
  506. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785496223183-AddMonitorSummaryToIncidentAndAlert.js +18 -0
  507. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785496223183-AddMonitorSummaryToIncidentAndAlert.js.map +1 -0
  508. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785516996695-AddSessionReplayReliabilityColumns.js +29 -0
  509. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785516996695-AddSessionReplayReliabilityColumns.js.map +1 -0
  510. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785533806494-AddSessionReplayCorrelationColumns.js +35 -0
  511. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785533806494-AddSessionReplayCorrelationColumns.js.map +1 -0
  512. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785749674203-AddRedisAndPostgresHealthNotificationColumns.js +40 -0
  513. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785749674203-AddRedisAndPostgresHealthNotificationColumns.js.map +1 -0
  514. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785763818197-AddAutoRemediation.js +128 -0
  515. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785763818197-AddAutoRemediation.js.map +1 -0
  516. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785768089408-AddRemediationVerification.js +28 -0
  517. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785768089408-AddRemediationVerification.js.map +1 -0
  518. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785776960660-AddRunnerCapabilities.js +14 -0
  519. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785776960660-AddRunnerCapabilities.js.map +1 -0
  520. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785790000000-AddIncidentInvestigationGating.js +27 -0
  521. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785790000000-AddIncidentInvestigationGating.js.map +1 -0
  522. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785800000000-AddRunbookCredential.js +44 -0
  523. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785800000000-AddRunbookCredential.js.map +1 -0
  524. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785810000000-RenameRunbookAgentToRunner.js +88 -0
  525. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785810000000-RenameRunbookAgentToRunner.js.map +1 -0
  526. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785860000000-SessionReplayDefaultToSensitiveInputMasking.js +59 -0
  527. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785860000000-SessionReplayDefaultToSensitiveInputMasking.js.map +1 -0
  528. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785870000000-AddAiCommandRemediation.js +76 -0
  529. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785870000000-AddAiCommandRemediation.js.map +1 -0
  530. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785880000000-AlignRunnerSchemaWithEntities.js +214 -0
  531. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785880000000-AlignRunnerSchemaWithEntities.js.map +1 -0
  532. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785890000000-AddFixVerificationAndAutomaticCodeFixes.js +44 -0
  533. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785890000000-AddFixVerificationAndAutomaticCodeFixes.js.map +1 -0
  534. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +32 -0
  535. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  536. package/build/dist/Server/Services/AIRunService.js +1 -4
  537. package/build/dist/Server/Services/AIRunService.js.map +1 -1
  538. package/build/dist/Server/Services/AIService.js +26 -0
  539. package/build/dist/Server/Services/AIService.js.map +1 -1
  540. package/build/dist/Server/Services/AlertService.js +37 -4
  541. package/build/dist/Server/Services/AlertService.js.map +1 -1
  542. package/build/dist/Server/Services/AlertSeverityService.js +24 -11
  543. package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
  544. package/build/dist/Server/Services/AlertStateService.js +24 -11
  545. package/build/dist/Server/Services/AlertStateService.js.map +1 -1
  546. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +917 -0
  547. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -0
  548. package/build/dist/Server/Services/{RunbookAgentOwnerTeamService.js → AutoRemediationRuleService.js} +2 -2
  549. package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -0
  550. package/build/dist/Server/Services/AutoRemediationSuggestionService.js +127 -0
  551. package/build/dist/Server/Services/AutoRemediationSuggestionService.js.map +1 -0
  552. package/build/dist/Server/Services/BillingService.js +45 -1
  553. package/build/dist/Server/Services/BillingService.js.map +1 -1
  554. package/build/dist/Server/Services/DatabaseService.js +72 -4
  555. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  556. package/build/dist/Server/Services/IncidentService.js +52 -4
  557. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  558. package/build/dist/Server/Services/IncidentSeverityService.js +24 -11
  559. package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
  560. package/build/dist/Server/Services/IncidentStateService.js +24 -11
  561. package/build/dist/Server/Services/IncidentStateService.js.map +1 -1
  562. package/build/dist/Server/Services/Index.js +18 -0
  563. package/build/dist/Server/Services/Index.js.map +1 -1
  564. package/build/dist/Server/Services/LlmProviderService.js +61 -8
  565. package/build/dist/Server/Services/LlmProviderService.js.map +1 -1
  566. package/build/dist/Server/Services/MonitorService.js +24 -0
  567. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  568. package/build/dist/Server/Services/MonitorStatusService.js +25 -11
  569. package/build/dist/Server/Services/MonitorStatusService.js.map +1 -1
  570. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +12 -11
  571. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
  572. package/build/dist/Server/Services/NetworkDeviceLabelRuleService.js +43 -0
  573. package/build/dist/Server/Services/NetworkDeviceLabelRuleService.js.map +1 -1
  574. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +12 -11
  575. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
  576. package/build/dist/Server/Services/NetworkDeviceOwnerRuleService.js +41 -0
  577. package/build/dist/Server/Services/NetworkDeviceOwnerRuleService.js.map +1 -1
  578. package/build/dist/Server/Services/NetworkDeviceService.js +129 -20
  579. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  580. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +67 -10
  581. package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -1
  582. package/build/dist/Server/Services/NetworkSiteService.js +19 -8
  583. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  584. package/build/dist/Server/Services/ProjectService.js +43 -0
  585. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  586. package/build/dist/Server/Services/RumApplicationService.js +202 -0
  587. package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
  588. package/build/dist/Server/Services/RumSessionChunkService.js +9 -0
  589. package/build/dist/Server/Services/RumSessionChunkService.js.map +1 -0
  590. package/build/dist/Server/Services/RumSessionErasureRequestService.js +190 -0
  591. package/build/dist/Server/Services/RumSessionErasureRequestService.js.map +1 -0
  592. package/build/dist/Server/Services/RumSessionPinService.js +208 -0
  593. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -0
  594. package/build/dist/Server/Services/RumSessionReplayViewService.js +180 -0
  595. package/build/dist/Server/Services/RumSessionReplayViewService.js.map +1 -0
  596. package/build/dist/Server/Services/RumSessionService.js +102 -0
  597. package/build/dist/Server/Services/RumSessionService.js.map +1 -0
  598. package/build/dist/Server/Services/RunbookCredentialService.js +67 -0
  599. package/build/dist/Server/Services/RunbookCredentialService.js.map +1 -0
  600. package/build/dist/Server/Services/{RunbookAgentJobService.js → RunnerJobService.js} +158 -46
  601. package/build/dist/Server/Services/RunnerJobService.js.map +1 -0
  602. package/build/dist/Server/Services/{RunbookAgentOwnerUserService.js → RunnerOwnerTeamService.js} +2 -2
  603. package/build/dist/Server/Services/RunnerOwnerTeamService.js.map +1 -0
  604. package/build/dist/Server/Services/RunnerOwnerUserService.js +9 -0
  605. package/build/dist/Server/Services/RunnerOwnerUserService.js.map +1 -0
  606. package/build/dist/Server/Services/RunnerService.js +163 -0
  607. package/build/dist/Server/Services/RunnerService.js.map +1 -0
  608. package/build/dist/Server/Services/ScheduledMaintenanceStateService.js +24 -11
  609. package/build/dist/Server/Services/ScheduledMaintenanceStateService.js.map +1 -1
  610. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +15 -1
  611. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  612. package/build/dist/Server/Services/ServiceService.js +8 -2
  613. package/build/dist/Server/Services/ServiceService.js.map +1 -1
  614. package/build/dist/Server/Services/StatusPageService.js +173 -16
  615. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  616. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +17 -1
  617. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
  618. package/build/dist/Server/Services/TelemetryExceptionService.js +3 -16
  619. package/build/dist/Server/Services/TelemetryExceptionService.js.map +1 -1
  620. package/build/dist/Server/Services/TelemetryUsageBillingService.js +31 -3
  621. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  622. package/build/dist/Server/Services/TraceAggregationService.js +106 -2
  623. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  624. package/build/dist/Server/Types/Billing/MeteredPlan/AllMeteredPlans.js +16 -0
  625. package/build/dist/Server/Types/Billing/MeteredPlan/AllMeteredPlans.js.map +1 -1
  626. package/build/dist/Server/Types/Billing/MeteredPlan/ServerMeteredPlan.js +9 -0
  627. package/build/dist/Server/Types/Billing/MeteredPlan/ServerMeteredPlan.js.map +1 -1
  628. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +38 -6
  629. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  630. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAuth.js +104 -0
  631. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAuth.js.map +1 -0
  632. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAvailability.js +54 -0
  633. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentAvailability.js.map +1 -0
  634. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +11 -7
  635. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
  636. package/build/dist/Server/Utils/AI/CodeFix/CodeFixRunQueue.js +3 -4
  637. package/build/dist/Server/Utils/AI/CodeFix/CodeFixRunQueue.js.map +1 -1
  638. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +724 -0
  639. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -0
  640. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +668 -0
  641. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -0
  642. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +657 -0
  643. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -0
  644. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +52 -7
  645. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  646. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +53 -5
  647. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  648. package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +25 -6
  649. package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -1
  650. package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +131 -17
  651. package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -1
  652. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +200 -5
  653. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  654. package/build/dist/Server/Utils/AI/SRE/Insights/Triage.js +2 -7
  655. package/build/dist/Server/Utils/AI/SRE/Insights/Triage.js.map +1 -1
  656. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +4 -17
  657. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
  658. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +203 -19
  659. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
  660. package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js +89 -0
  661. package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js.map +1 -0
  662. package/build/dist/Server/Utils/AI/SRE/RemediationHandoff.js +82 -0
  663. package/build/dist/Server/Utils/AI/SRE/RemediationHandoff.js.map +1 -0
  664. package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +4 -19
  665. package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -1
  666. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +2 -2
  667. package/build/dist/Server/Utils/Alert/AlertPrivacyFilter.js +36 -0
  668. package/build/dist/Server/Utils/Alert/AlertPrivacyFilter.js.map +1 -1
  669. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +498 -0
  670. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -0
  671. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +492 -0
  672. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -0
  673. package/build/dist/Server/Utils/CorsOptions.js +47 -0
  674. package/build/dist/Server/Utils/CorsOptions.js.map +1 -0
  675. package/build/dist/Server/Utils/Database/RelationIdUtil.js +51 -0
  676. package/build/dist/Server/Utils/Database/RelationIdUtil.js.map +1 -0
  677. package/build/dist/Server/Utils/Incident/IncidentPrivacyFilter.js +38 -0
  678. package/build/dist/Server/Utils/Incident/IncidentPrivacyFilter.js.map +1 -1
  679. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +194 -0
  680. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +1 -0
  681. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +292 -0
  682. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -0
  683. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +11 -0
  684. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  685. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +9 -0
  686. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  687. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +9 -0
  688. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  689. package/build/dist/Server/Utils/Monitor/MonitorResource.js +16 -0
  690. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  691. package/build/dist/Server/Utils/Monitor/MonitorSummaryCapture.js +92 -0
  692. package/build/dist/Server/Utils/Monitor/MonitorSummaryCapture.js.map +1 -0
  693. package/build/dist/Server/Utils/NetworkDevice/RulePatternValidator.js +27 -0
  694. package/build/dist/Server/Utils/NetworkDevice/RulePatternValidator.js.map +1 -0
  695. package/build/dist/Server/Utils/OpenAPI.js +2 -1
  696. package/build/dist/Server/Utils/OpenAPI.js.map +1 -1
  697. package/build/dist/Server/Utils/Runbook/RunbookExecutePermission.js +67 -0
  698. package/build/dist/Server/Utils/Runbook/RunbookExecutePermission.js.map +1 -0
  699. package/build/dist/Server/Utils/SessionReplay/SessionReplayErasureTombstone.js +98 -0
  700. package/build/dist/Server/Utils/SessionReplay/SessionReplayErasureTombstone.js.map +1 -0
  701. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +378 -0
  702. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -0
  703. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js +137 -0
  704. package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js.map +1 -0
  705. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +998 -0
  706. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -0
  707. package/build/dist/Server/Utils/SessionReplay/SessionReplayRetention.js +59 -0
  708. package/build/dist/Server/Utils/SessionReplay/SessionReplayRetention.js.map +1 -0
  709. package/build/dist/Server/Utils/SessionReplay/SessionReplayTargeting.js +98 -0
  710. package/build/dist/Server/Utils/SessionReplay/SessionReplayTargeting.js.map +1 -0
  711. package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +69 -0
  712. package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -0
  713. package/build/dist/Server/Utils/StartServer.js +40 -3
  714. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  715. package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js +27 -6
  716. package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -1
  717. package/build/dist/Types/AI/AIRunStatus.js +17 -5
  718. package/build/dist/Types/AI/AIRunStatus.js.map +1 -1
  719. package/build/dist/Types/AI/AIRunType.js +18 -0
  720. package/build/dist/Types/AI/AIRunType.js.map +1 -1
  721. package/build/dist/Types/AI/FixVerificationStatus.js +22 -0
  722. package/build/dist/Types/AI/FixVerificationStatus.js.map +1 -0
  723. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +16 -0
  724. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  725. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +192 -0
  726. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -0
  727. package/build/dist/Types/AutoRemediation/AutoRemediationExecutionMode.js +18 -0
  728. package/build/dist/Types/AutoRemediation/AutoRemediationExecutionMode.js.map +1 -0
  729. package/build/dist/Types/AutoRemediation/AutoRemediationSuggestionStatus.js +31 -0
  730. package/build/dist/Types/AutoRemediation/AutoRemediationSuggestionStatus.js.map +1 -0
  731. package/build/dist/Types/AutoRemediation/AutoRemediationSuggestionType.js +18 -0
  732. package/build/dist/Types/AutoRemediation/AutoRemediationSuggestionType.js.map +1 -0
  733. package/build/dist/Types/AutoRemediation/AutoRemediationTriggerEntity.js +12 -0
  734. package/build/dist/Types/AutoRemediation/AutoRemediationTriggerEntity.js.map +1 -0
  735. package/build/dist/Types/AutoRemediation/AutoRemediationVerificationStatus.js +22 -0
  736. package/build/dist/Types/AutoRemediation/AutoRemediationVerificationStatus.js.map +1 -0
  737. package/build/dist/Types/CustomField/CustomFieldDropdownOption.js +110 -0
  738. package/build/dist/Types/CustomField/CustomFieldDropdownOption.js.map +1 -0
  739. package/build/dist/Types/Dashboard/DashboardComponentType.js +2 -0
  740. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  741. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +4 -0
  742. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  743. package/build/dist/Types/Dashboard/DashboardComponents/DashboardClockComponent.js +19 -0
  744. package/build/dist/Types/Dashboard/DashboardComponents/DashboardClockComponent.js.map +1 -0
  745. package/build/dist/Types/Dashboard/DashboardComponents/DashboardHtmlComponent.js +2 -0
  746. package/build/dist/Types/Dashboard/DashboardComponents/DashboardHtmlComponent.js.map +1 -0
  747. package/build/dist/Types/Dashboard/DashboardTemplates.js +487 -0
  748. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  749. package/build/dist/Types/Date.js +6 -0
  750. package/build/dist/Types/Date.js.map +1 -1
  751. package/build/dist/Types/Email/EmailTemplateType.js +2 -0
  752. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  753. package/build/dist/Types/Kubernetes/KubernetesRightSizing.js +229 -0
  754. package/build/dist/Types/Kubernetes/KubernetesRightSizing.js.map +1 -0
  755. package/build/dist/Types/MeteredPlan/ProductType.js +1 -0
  756. package/build/dist/Types/MeteredPlan/ProductType.js.map +1 -1
  757. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js +12 -2
  758. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js.map +1 -1
  759. package/build/dist/Types/Monitor/MonitorSteps.js +5 -0
  760. package/build/dist/Types/Monitor/MonitorSteps.js.map +1 -1
  761. package/build/dist/Types/Monitor/MonitorSummarySnapshot.js +13 -0
  762. package/build/dist/Types/Monitor/MonitorSummarySnapshot.js.map +1 -0
  763. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +40 -8
  764. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  765. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +4 -3
  766. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  767. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +50 -10
  768. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
  769. package/build/dist/Types/Monitor/RumAlertTemplates.js +297 -0
  770. package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -0
  771. package/build/dist/Types/Permission.js +184 -24
  772. package/build/dist/Types/Permission.js.map +1 -1
  773. package/build/dist/Types/Rum/SessionReplay.js +155 -0
  774. package/build/dist/Types/Rum/SessionReplay.js.map +1 -0
  775. package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js +26 -0
  776. package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js.map +1 -0
  777. package/build/dist/Types/Rum/SessionReplayConsentMode.js +27 -0
  778. package/build/dist/Types/Rum/SessionReplayConsentMode.js.map +1 -0
  779. package/build/dist/Types/Rum/SessionReplayMaskingMode.js +79 -0
  780. package/build/dist/Types/Rum/SessionReplayMaskingMode.js.map +1 -0
  781. package/build/dist/Types/Rum/SessionReplayTriggerReason.js +28 -0
  782. package/build/dist/Types/Rum/SessionReplayTriggerReason.js.map +1 -0
  783. package/build/dist/Types/Runbook/RunbookCredentialType.js +7 -0
  784. package/build/dist/Types/Runbook/RunbookCredentialType.js.map +1 -0
  785. package/build/dist/Types/Runbook/RunbookStep.js +20 -1
  786. package/build/dist/Types/Runbook/RunbookStep.js.map +1 -1
  787. package/build/dist/Types/Runbook/RunbookStepType.js +24 -0
  788. package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
  789. package/build/dist/Types/Runbook/RunnerJobOrigin.js +21 -0
  790. package/build/dist/Types/Runbook/RunnerJobOrigin.js.map +1 -0
  791. package/build/dist/Types/Runbook/RunnerJobStatus.js +22 -0
  792. package/build/dist/Types/Runbook/RunnerJobStatus.js.map +1 -0
  793. package/build/dist/Types/Runner/RunnerLiveStatus.js +69 -0
  794. package/build/dist/Types/Runner/RunnerLiveStatus.js.map +1 -0
  795. package/build/dist/Types/StatusPage/StatusPageReport.js +22 -0
  796. package/build/dist/Types/StatusPage/StatusPageReport.js.map +1 -0
  797. package/build/dist/Types/Telemetry/TelemetryRetentionConfig.js.map +1 -1
  798. package/build/dist/Types/Text.js +29 -0
  799. package/build/dist/Types/Text.js.map +1 -1
  800. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +143 -28
  801. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
  802. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js +82 -9
  803. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js.map +1 -1
  804. package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js +11 -0
  805. package/build/dist/UI/Components/BulkUpdate/BulkOwnerActions.js.map +1 -1
  806. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +11 -13
  807. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  808. package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js +76 -45
  809. package/build/dist/UI/Components/CustomFields/DropdownOptionsInput.js.map +1 -1
  810. package/build/dist/UI/Components/Detail/Detail.js +100 -8
  811. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  812. package/build/dist/UI/Components/Dropdown/Dropdown.js +2 -5
  813. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  814. package/build/dist/UI/Components/Dropdown/DropdownMenuZIndex.js +7 -0
  815. package/build/dist/UI/Components/Dropdown/DropdownMenuZIndex.js.map +1 -0
  816. package/build/dist/UI/Components/Dropdown/DropdownValueBadge.js +32 -0
  817. package/build/dist/UI/Components/Dropdown/DropdownValueBadge.js.map +1 -0
  818. package/build/dist/UI/Components/Filters/OperatorSelector.js +210 -20
  819. package/build/dist/UI/Components/Filters/OperatorSelector.js.map +1 -1
  820. package/build/dist/UI/Components/Forms/Fields/ColorPicker.js +26 -10
  821. package/build/dist/UI/Components/Forms/Fields/ColorPicker.js.map +1 -1
  822. package/build/dist/UI/Components/Forms/Fields/IconPicker.js +28 -13
  823. package/build/dist/UI/Components/Forms/Fields/IconPicker.js.map +1 -1
  824. package/build/dist/UI/Components/Forms/Validation.js +9 -5
  825. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  826. package/build/dist/UI/Components/List/List.js +1 -1
  827. package/build/dist/UI/Components/List/List.js.map +1 -1
  828. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +21 -19
  829. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
  830. package/build/dist/UI/Components/Pagination/Pagination.js +14 -3
  831. package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
  832. package/build/dist/UI/Components/Table/Table.js +1 -1
  833. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  834. package/build/dist/UI/Types/UseAnchoredFieldPopup.js +197 -0
  835. package/build/dist/UI/Types/UseAnchoredFieldPopup.js.map +1 -0
  836. package/build/dist/UI/Utils/Dropdown.js +18 -0
  837. package/build/dist/UI/Utils/Dropdown.js.map +1 -1
  838. package/build/dist/UI/Utils/Timezone.js +13 -2
  839. package/build/dist/UI/Utils/Timezone.js.map +1 -1
  840. package/build/dist/UI/Utils/UseClockTick.js +41 -0
  841. package/build/dist/UI/Utils/UseClockTick.js.map +1 -0
  842. package/build/dist/Utils/AiRemediation/CommandPolicy.js +303 -0
  843. package/build/dist/Utils/AiRemediation/CommandPolicy.js.map +1 -0
  844. package/build/dist/Utils/Dashboard/ClockWidgetFormat.js +232 -0
  845. package/build/dist/Utils/Dashboard/ClockWidgetFormat.js.map +1 -0
  846. package/build/dist/Utils/Dashboard/Components/DashboardClockComponent.js +146 -0
  847. package/build/dist/Utils/Dashboard/Components/DashboardClockComponent.js.map +1 -0
  848. package/build/dist/Utils/Dashboard/Components/DashboardHtmlComponent.js +133 -0
  849. package/build/dist/Utils/Dashboard/Components/DashboardHtmlComponent.js.map +1 -0
  850. package/build/dist/Utils/Dashboard/Components/DashboardValueComponent.js +10 -1
  851. package/build/dist/Utils/Dashboard/Components/DashboardValueComponent.js.map +1 -1
  852. package/build/dist/Utils/Dashboard/Components/Index.js +8 -0
  853. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  854. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js +198 -0
  855. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js.map +1 -0
  856. package/build/dist/Utils/Dashboard/ValueWidgetLayout.js +276 -0
  857. package/build/dist/Utils/Dashboard/ValueWidgetLayout.js.map +1 -0
  858. package/build/dist/Utils/Metrics/MetricSeriesScope.js +203 -0
  859. package/build/dist/Utils/Metrics/MetricSeriesScope.js.map +1 -0
  860. package/build/dist/Utils/Monitor/MonitorSummarySnapshotUtil.js +382 -0
  861. package/build/dist/Utils/Monitor/MonitorSummarySnapshotUtil.js.map +1 -0
  862. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +13 -7
  863. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -1
  864. package/build/dist/Utils/Rules/RulePatternMatchUtil.js +87 -0
  865. package/build/dist/Utils/Rules/RulePatternMatchUtil.js.map +1 -0
  866. package/build/dist/Utils/Rum/ChunkMath.js +147 -0
  867. package/build/dist/Utils/Rum/ChunkMath.js.map +1 -0
  868. package/build/dist/Utils/Rum/Masking.js +143 -0
  869. package/build/dist/Utils/Rum/Masking.js.map +1 -0
  870. package/build/dist/Utils/Rum/SessionIdentity.js +161 -0
  871. package/build/dist/Utils/Rum/SessionIdentity.js.map +1 -0
  872. package/build/dist/Utils/Rum/SessionSampling.js +91 -0
  873. package/build/dist/Utils/Rum/SessionSampling.js.map +1 -0
  874. package/build/dist/Utils/Rum/UrlScrubber.js +144 -0
  875. package/build/dist/Utils/Rum/UrlScrubber.js.map +1 -0
  876. package/build/dist/Utils/Schema/ModelSchema.js +28 -3
  877. package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
  878. package/build/dist/Utils/StatusPage/Report.js +194 -0
  879. package/build/dist/Utils/StatusPage/Report.js.map +1 -0
  880. package/build/dist/Utils/ValueFormatter.js +239 -46
  881. package/build/dist/Utils/ValueFormatter.js.map +1 -1
  882. package/jest.config.json +3 -0
  883. package/package.json +1 -1
  884. package/tsconfig.json +19 -1
  885. package/Server/Services/RunbookAgentService.ts +0 -93
  886. package/build/dist/Models/DatabaseModels/RunbookAgent.js.map +0 -1
  887. package/build/dist/Models/DatabaseModels/RunbookAgentJob.js.map +0 -1
  888. package/build/dist/Models/DatabaseModels/RunbookAgentOwnerTeam.js.map +0 -1
  889. package/build/dist/Models/DatabaseModels/RunbookAgentOwnerUser.js.map +0 -1
  890. package/build/dist/Server/Services/RunbookAgentJobService.js.map +0 -1
  891. package/build/dist/Server/Services/RunbookAgentOwnerTeamService.js.map +0 -1
  892. package/build/dist/Server/Services/RunbookAgentOwnerUserService.js.map +0 -1
  893. package/build/dist/Server/Services/RunbookAgentService.js +0 -91
  894. package/build/dist/Server/Services/RunbookAgentService.js.map +0 -1
  895. package/build/dist/Types/Runbook/RunbookAgentJobStatus.js +0 -22
  896. package/build/dist/Types/Runbook/RunbookAgentJobStatus.js.map +0 -1
@@ -0,0 +1,1255 @@
1
+ import { beforeEach, describe, expect, jest, test } from "@jest/globals";
2
+ import "@testing-library/jest-dom";
3
+ import {
4
+ act,
5
+ fireEvent,
6
+ render,
7
+ renderHook,
8
+ screen,
9
+ waitFor,
10
+ } from "@testing-library/react";
11
+ import * as React from "react";
12
+ import { FunctionComponent, ReactElement } from "react";
13
+ import getJestMockFunction, { MockFunction } from "../../MockType";
14
+
15
+ /*
16
+ * Scope: this is baseline coverage, not change coverage. Read the green count
17
+ * accordingly. useBulkOwnerActions is a shared hook that shipped with no tests
18
+ * at all, and all but two of the cases below characterise behaviour that
19
+ * already existed - they pass just as well against the pre-change hook. They
20
+ * are written now because this change is what makes the SLO lists depend on
21
+ * that behaviour.
22
+ *
23
+ * Exactly two tests pin this change: "opening Add Owner closes an open Remove
24
+ * Owner modal" and "opening Remove Owner closes an open Add Owner modal". The
25
+ * hook now clears the sibling modal's flag, and both fail without it.
26
+ *
27
+ * The model under test is the ServiceLevelObjectiveOwnerUser /
28
+ * ServiceLevelObjectiveOwnerTeam junction pair because the SLO lists are the
29
+ * adoption this change adds; the hook itself is model-agnostic.
30
+ *
31
+ * The hook is not a thin wrapper: it flattens every team's membership into a
32
+ * single de-duped people list, tags each option with a "user:"/"team:" prefix
33
+ * so one dropdown can drive two different junction tables, and then - per
34
+ * selected item - reads that item's existing owners so a second "Add Owner"
35
+ * run does not create duplicate rows. Every one of those steps is silent when
36
+ * it goes wrong: a wrong resourceIdField or a dropped prefix does not fail, it
37
+ * just queries nothing and reports the item as a success. So the suite drives
38
+ * the real modal, the real form and the real dropdown, and asserts on what
39
+ * actually reaches ModelAPI.
40
+ */
41
+
42
+ /*
43
+ * react-i18next is not initialized in the test environment. Mock the hook so
44
+ * translate helpers echo their input and the component renders synchronously.
45
+ */
46
+ jest.mock("react-i18next", () => {
47
+ return {
48
+ useTranslation: () => {
49
+ return {
50
+ t: (key: string, opts?: { defaultValue?: string }): string => {
51
+ return opts?.defaultValue ?? key;
52
+ },
53
+ };
54
+ },
55
+ };
56
+ });
57
+
58
+ /*
59
+ * Declared before jest.mock but dereferenced inside the factory: ts-jest
60
+ * hoists the jest.mock call above these initializers, so naming the mocks
61
+ * directly in the factory would capture undefined.
62
+ */
63
+ const getListMock: MockFunction = getJestMockFunction();
64
+ const createMock: MockFunction = getJestMockFunction();
65
+ const deleteItemMock: MockFunction = getJestMockFunction();
66
+
67
+ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
68
+ return {
69
+ __esModule: true,
70
+ default: {
71
+ getList: (...args: Array<any>) => {
72
+ return getListMock(...args);
73
+ },
74
+ create: (...args: Array<any>) => {
75
+ return createMock(...args);
76
+ },
77
+ deleteItem: (...args: Array<any>) => {
78
+ return deleteItemMock(...args);
79
+ },
80
+ },
81
+ };
82
+ });
83
+
84
+ import useBulkOwnerActions, {
85
+ BulkOwnerActionsConfig,
86
+ BulkOwnerActionsResult,
87
+ } from "../../../UI/Components/BulkUpdate/BulkOwnerActions";
88
+ import {
89
+ BulkActionButtonSchema,
90
+ BulkActionFailed,
91
+ BulkActionOnClickProps,
92
+ ProgressInfo,
93
+ } from "../../../UI/Components/BulkUpdate/BulkUpdateForm";
94
+ import { ButtonStyleType } from "../../../UI/Components/Button/Button";
95
+ import ServiceLevelObjective from "../../../Models/DatabaseModels/ServiceLevelObjective";
96
+ import ServiceLevelObjectiveOwnerTeam from "../../../Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam";
97
+ import ServiceLevelObjectiveOwnerUser from "../../../Models/DatabaseModels/ServiceLevelObjectiveOwnerUser";
98
+ import Team from "../../../Models/DatabaseModels/Team";
99
+ import TeamMember from "../../../Models/DatabaseModels/TeamMember";
100
+ import User from "../../../Models/DatabaseModels/User";
101
+ import Includes from "../../../Types/BaseDatabase/Includes";
102
+ import SortOrder from "../../../Types/BaseDatabase/SortOrder";
103
+ import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
104
+ import BadDataException from "../../../Types/Exception/BadDataException";
105
+ import Email from "../../../Types/Email";
106
+ import IconProp from "../../../Types/Icon/IconProp";
107
+ import Name from "../../../Types/Name";
108
+ import ObjectID from "../../../Types/ObjectID";
109
+
110
+ /*
111
+ * Rendering the real modal pulls in Formik and react-select, which are slow
112
+ * to mount on a loaded box; the testing-library default of 1s flakes there.
113
+ */
114
+ const WAIT_TIMEOUT: number = 20000;
115
+
116
+ const PROJECT_ID: string = "11111111-1111-4111-8111-111111111111";
117
+ const SLO_ONE_ID: string = "22222222-2222-4222-8222-222222222221";
118
+ const SLO_TWO_ID: string = "22222222-2222-4222-8222-222222222222";
119
+ const ALICE_ID: string = "33333333-3333-4333-8333-333333333331";
120
+ const BOB_ID: string = "33333333-3333-4333-8333-333333333332";
121
+ const CAROL_ID: string = "33333333-3333-4333-8333-333333333333";
122
+ const TEAM_ONE_ID: string = "44444444-4444-4444-8444-444444444441";
123
+ const TEAM_TWO_ID: string = "44444444-4444-4444-8444-444444444442";
124
+ const OWNER_ROW_ID: string = "55555555-5555-4555-8555-555555555551";
125
+ const OWNER_ROW_TWO_ID: string = "55555555-5555-4555-8555-555555555552";
126
+
127
+ const SLO_OWNER_CONFIG: BulkOwnerActionsConfig = {
128
+ ownerUserModelType: ServiceLevelObjectiveOwnerUser,
129
+ ownerTeamModelType: ServiceLevelObjectiveOwnerTeam,
130
+ resourceIdField: "serviceLevelObjectiveId",
131
+ };
132
+
133
+ interface TeamMemberSeed {
134
+ userId: string;
135
+ name?: string;
136
+ email?: string;
137
+ }
138
+
139
+ type MakeTeamMemberFunction = (seed: TeamMemberSeed) => TeamMember;
140
+
141
+ const makeTeamMember: MakeTeamMemberFunction = (
142
+ seed: TeamMemberSeed,
143
+ ): TeamMember => {
144
+ const user: User = new User();
145
+ user._id = seed.userId;
146
+
147
+ if (seed.name) {
148
+ user.name = new Name(seed.name);
149
+ }
150
+
151
+ if (seed.email) {
152
+ user.email = new Email(seed.email);
153
+ }
154
+
155
+ const member: TeamMember = new TeamMember();
156
+ member.user = user;
157
+
158
+ return member;
159
+ };
160
+
161
+ type MakeTeamFunction = (id: string, name: string) => Team;
162
+
163
+ const makeTeam: MakeTeamFunction = (id: string, name: string): Team => {
164
+ const team: Team = new Team();
165
+ team._id = id;
166
+ team.name = name;
167
+
168
+ return team;
169
+ };
170
+
171
+ type MakeSloFunction = (id?: string) => ServiceLevelObjective;
172
+
173
+ const makeSlo: MakeSloFunction = (id?: string): ServiceLevelObjective => {
174
+ const slo: ServiceLevelObjective = new ServiceLevelObjective();
175
+
176
+ if (id) {
177
+ slo._id = id;
178
+ }
179
+
180
+ return slo;
181
+ };
182
+
183
+ interface OwnerRowSeed {
184
+ id?: string;
185
+ userId?: string;
186
+ teamId?: string;
187
+ }
188
+
189
+ type MakeOwnerUserRowFunction = (
190
+ seed: OwnerRowSeed,
191
+ ) => ServiceLevelObjectiveOwnerUser;
192
+
193
+ const makeOwnerUserRow: MakeOwnerUserRowFunction = (
194
+ seed: OwnerRowSeed,
195
+ ): ServiceLevelObjectiveOwnerUser => {
196
+ const row: ServiceLevelObjectiveOwnerUser =
197
+ new ServiceLevelObjectiveOwnerUser();
198
+
199
+ if (seed.id) {
200
+ row._id = seed.id;
201
+ }
202
+
203
+ if (seed.userId) {
204
+ row.userId = new ObjectID(seed.userId);
205
+ }
206
+
207
+ return row;
208
+ };
209
+
210
+ type MakeOwnerTeamRowFunction = (
211
+ seed: OwnerRowSeed,
212
+ ) => ServiceLevelObjectiveOwnerTeam;
213
+
214
+ const makeOwnerTeamRow: MakeOwnerTeamRowFunction = (
215
+ seed: OwnerRowSeed,
216
+ ): ServiceLevelObjectiveOwnerTeam => {
217
+ const row: ServiceLevelObjectiveOwnerTeam =
218
+ new ServiceLevelObjectiveOwnerTeam();
219
+
220
+ if (seed.id) {
221
+ row._id = seed.id;
222
+ }
223
+
224
+ if (seed.teamId) {
225
+ row.teamId = new ObjectID(seed.teamId);
226
+ }
227
+
228
+ return row;
229
+ };
230
+
231
+ interface ListSeeds {
232
+ teamMembers?: Array<TeamMember>;
233
+ teams?: Array<Team>;
234
+ ownerUsers?: Array<ServiceLevelObjectiveOwnerUser>;
235
+ ownerTeams?: Array<ServiceLevelObjectiveOwnerTeam>;
236
+ }
237
+
238
+ type MockListsFunction = (seeds: ListSeeds) => void;
239
+
240
+ /*
241
+ * All four reads go through the same ModelAPI.getList, so every assertion
242
+ * about "which table did it ask for" has to branch on modelType rather than
243
+ * on call order.
244
+ */
245
+ const mockLists: MockListsFunction = (seeds: ListSeeds): void => {
246
+ getListMock.mockImplementation(async (listData: any): Promise<any> => {
247
+ let rows: Array<any> = [];
248
+
249
+ if (listData.modelType === TeamMember) {
250
+ rows = seeds.teamMembers || [];
251
+ } else if (listData.modelType === Team) {
252
+ rows = seeds.teams || [];
253
+ } else if (listData.modelType === ServiceLevelObjectiveOwnerUser) {
254
+ rows = seeds.ownerUsers || [];
255
+ } else if (listData.modelType === ServiceLevelObjectiveOwnerTeam) {
256
+ rows = seeds.ownerTeams || [];
257
+ }
258
+
259
+ return {
260
+ data: rows,
261
+ count: rows.length,
262
+ skip: 0,
263
+ limit: LIMIT_PER_PROJECT,
264
+ };
265
+ });
266
+ };
267
+
268
+ interface ProgressSnapshot {
269
+ totalItems: Array<string>;
270
+ inProgressItems: Array<string>;
271
+ successItems: Array<string>;
272
+ failed: Array<{ id: string; failedMessage: string }>;
273
+ }
274
+
275
+ const progressSnapshots: Array<ProgressSnapshot> = [];
276
+
277
+ const onProgressInfo: MockFunction = getJestMockFunction();
278
+ const onBulkActionStart: MockFunction = getJestMockFunction();
279
+ const onBulkActionEnd: MockFunction = getJestMockFunction();
280
+
281
+ type IdsOfFunction = (items: Array<ServiceLevelObjective>) => Array<string>;
282
+
283
+ const idsOf: IdsOfFunction = (
284
+ items: Array<ServiceLevelObjective>,
285
+ ): Array<string> => {
286
+ return items.map((item: ServiceLevelObjective) => {
287
+ return item._id || "no-id";
288
+ });
289
+ };
290
+
291
+ interface HarnessProps {
292
+ items: Array<ServiceLevelObjective>;
293
+ }
294
+
295
+ /*
296
+ * The hook hands back action descriptors that render nothing plus a `modals`
297
+ * element, so the modals only exist once something mounts them - renderHook
298
+ * alone cannot reach the form.
299
+ */
300
+ const Harness: FunctionComponent<HarnessProps> = (
301
+ props: HarnessProps,
302
+ ): ReactElement => {
303
+ const { bulkActions, modals }: BulkOwnerActionsResult<ServiceLevelObjective> =
304
+ useBulkOwnerActions<ServiceLevelObjective>(SLO_OWNER_CONFIG);
305
+
306
+ return (
307
+ <div>
308
+ {bulkActions.map(
309
+ (action: BulkActionButtonSchema<ServiceLevelObjective>) => {
310
+ return (
311
+ <button
312
+ key={action.title}
313
+ type="button"
314
+ onClick={() => {
315
+ void action.onClick({
316
+ items: props.items,
317
+ onProgressInfo: onProgressInfo,
318
+ onBulkActionStart: onBulkActionStart,
319
+ onBulkActionEnd: onBulkActionEnd,
320
+ } as BulkActionOnClickProps<ServiceLevelObjective>);
321
+ }}
322
+ >
323
+ {`Trigger ${action.title}`}
324
+ </button>
325
+ );
326
+ },
327
+ )}
328
+ {modals}
329
+ </div>
330
+ );
331
+ };
332
+
333
+ type WaitForOwnerSourcesFunction = () => Promise<void>;
334
+
335
+ const waitForOwnerSources: WaitForOwnerSourcesFunction =
336
+ async (): Promise<void> => {
337
+ /*
338
+ * Drained inside act() first: waitFor's own await would otherwise let
339
+ * the mount fetch settle between checks, landing the dropdown state
340
+ * outside act and burying the run in warnings.
341
+ */
342
+ await act(async () => {
343
+ await new Promise<void>((resolve: () => void) => {
344
+ setTimeout(resolve, 0);
345
+ });
346
+ });
347
+
348
+ await waitFor(
349
+ () => {
350
+ expect(getListMock).toHaveBeenCalledTimes(2);
351
+ },
352
+ { timeout: WAIT_TIMEOUT },
353
+ );
354
+ };
355
+
356
+ type OpenOwnerModalFunction = (title: string) => Promise<void>;
357
+
358
+ const openOwnerModal: OpenOwnerModalFunction = async (
359
+ title: string,
360
+ ): Promise<void> => {
361
+ fireEvent.click(screen.getByText(`Trigger ${title}`));
362
+
363
+ await waitFor(
364
+ () => {
365
+ expect(screen.getByTestId("modal-title")).toHaveTextContent(title);
366
+ },
367
+ { timeout: WAIT_TIMEOUT },
368
+ );
369
+ };
370
+
371
+ type ClickOwnerActionFunction = (title: string) => void;
372
+
373
+ /*
374
+ * openOwnerModal is unusable for the exclusion tests: its getByTestId gate
375
+ * throws on a multiple match, so a stacked second modal makes the helper spin
376
+ * until the test times out and neither assertion ever runs. Clicking without
377
+ * the gate leaves the count assertion as the thing that reports the
378
+ * regression. Safe to read the DOM straight after: fireEvent is act-wrapped
379
+ * and the onClick sets both flags before its first await.
380
+ */
381
+ const clickOwnerAction: ClickOwnerActionFunction = (title: string): void => {
382
+ fireEvent.click(screen.getByText(`Trigger ${title}`));
383
+ };
384
+
385
+ type SelectOwnerFunction = (optionLabel: string) => Promise<void>;
386
+
387
+ /*
388
+ * react-select closes its menu after each pick and hides already-selected
389
+ * options, so re-opening between picks is what makes multi-select reachable
390
+ * and keeps the option text unambiguous against the value pill.
391
+ */
392
+ const selectOwner: SelectOwnerFunction = async (
393
+ optionLabel: string,
394
+ ): Promise<void> => {
395
+ const combobox: HTMLElement = screen.getByRole("combobox");
396
+ fireEvent.keyDown(combobox, { key: "ArrowDown", code: "ArrowDown" });
397
+ fireEvent.click(
398
+ await screen.findByText(optionLabel, {}, { timeout: WAIT_TIMEOUT }),
399
+ );
400
+ };
401
+
402
+ type OpenOwnerMenuFunction = () => void;
403
+
404
+ const openOwnerMenu: OpenOwnerMenuFunction = (): void => {
405
+ const combobox: HTMLElement = screen.getByRole("combobox");
406
+ fireEvent.keyDown(combobox, { key: "ArrowDown", code: "ArrowDown" });
407
+ };
408
+
409
+ type SubmitOwnerModalFunction = () => void;
410
+
411
+ const submitOwnerModal: SubmitOwnerModalFunction = (): void => {
412
+ fireEvent.click(screen.getByTestId("modal-footer-submit-button"));
413
+ };
414
+
415
+ type GetListCallsForFunction = (modelType: unknown) => Array<any>;
416
+
417
+ const getListCallsFor: GetListCallsForFunction = (
418
+ modelType: unknown,
419
+ ): Array<any> => {
420
+ return (getListMock.mock.calls as Array<Array<any>>)
421
+ .map((call: Array<any>) => {
422
+ return call[0];
423
+ })
424
+ .filter((listData: any) => {
425
+ return listData.modelType === modelType;
426
+ });
427
+ };
428
+
429
+ /*
430
+ * These mount the real Modal, Formik and react-select trees, so a cold
431
+ * ts-jest transform of that import graph can push individual tests past
432
+ * jest's 5s default - which CI, always starting cold, would report as a
433
+ * red build with no assertion having failed. The slowest test here runs
434
+ * in ~1.3s warm; 30s is the same ceiling App/jest.config.json already
435
+ * sets for its whole suite.
436
+ */
437
+ jest.setTimeout(30000);
438
+
439
+ describe("useBulkOwnerActions", () => {
440
+ beforeEach(() => {
441
+ jest.clearAllMocks();
442
+ progressSnapshots.length = 0;
443
+ window.localStorage.clear();
444
+ window.sessionStorage.clear();
445
+
446
+ /*
447
+ * ProjectUtil.getCurrentProjectId() reads pathname.split("/")[2] before
448
+ * falling back to storage, so the URL is the whole "current project"
449
+ * fixture.
450
+ */
451
+ window.history.replaceState({}, "", `/dashboard/${PROJECT_ID}/slos`);
452
+
453
+ /*
454
+ * The progress arrays are allocated once and handed to every callback by
455
+ * reference, so anything kept without copying reads back as the final
456
+ * state of the run.
457
+ */
458
+ onProgressInfo.mockImplementation(
459
+ (progressInfo: ProgressInfo<ServiceLevelObjective>): void => {
460
+ progressSnapshots.push({
461
+ totalItems: idsOf(progressInfo.totalItems),
462
+ inProgressItems: idsOf(progressInfo.inProgressItems),
463
+ successItems: idsOf(progressInfo.successItems),
464
+ failed: progressInfo.failed.map(
465
+ (failure: BulkActionFailed<ServiceLevelObjective>) => {
466
+ return {
467
+ id: failure.item._id || "no-id",
468
+ failedMessage: failure.failedMessage as string,
469
+ };
470
+ },
471
+ ),
472
+ });
473
+ },
474
+ );
475
+
476
+ mockLists({});
477
+ createMock.mockResolvedValue({});
478
+ deleteItemMock.mockResolvedValue({});
479
+ });
480
+
481
+ test("offers Add Owner then Remove Owner, in that order", async () => {
482
+ const { result } = renderHook(() => {
483
+ return useBulkOwnerActions<ServiceLevelObjective>(SLO_OWNER_CONFIG);
484
+ });
485
+
486
+ await waitForOwnerSources();
487
+
488
+ /*
489
+ * Consumers splice these straight into ModelTable's button list, which
490
+ * renders them in array order.
491
+ */
492
+ expect(result.current.bulkActions).toHaveLength(2);
493
+ expect(result.current.bulkActions[0]!.title).toBe("Add Owner");
494
+ expect(result.current.bulkActions[1]!.title).toBe("Remove Owner");
495
+ });
496
+
497
+ test("gives both actions the user icons and a non-danger button style", async () => {
498
+ const { result } = renderHook(() => {
499
+ return useBulkOwnerActions<ServiceLevelObjective>(SLO_OWNER_CONFIG);
500
+ });
501
+
502
+ await waitForOwnerSources();
503
+
504
+ expect(result.current.bulkActions[0]!.icon).toBe(IconProp.UserPlus);
505
+ expect(result.current.bulkActions[0]!.buttonStyleType).toBe(
506
+ ButtonStyleType.NORMAL,
507
+ );
508
+ expect(result.current.bulkActions[1]!.icon).toBe(IconProp.UserMinus);
509
+
510
+ /*
511
+ * BulkUpdateForm splits danger-styled buttons into their own red menu
512
+ * group below a divider. Removing an owner is reversible, so it has to
513
+ * stay with the ordinary actions.
514
+ */
515
+ expect(result.current.bulkActions[1]!.buttonStyleType).toBe(
516
+ ButtonStyleType.NORMAL,
517
+ );
518
+ });
519
+
520
+ test("fetches this project's team members and teams on mount", async () => {
521
+ render(<Harness items={[]} />);
522
+
523
+ await waitForOwnerSources();
524
+
525
+ const memberCall: any = getListCallsFor(TeamMember)[0];
526
+ expect(memberCall.query.projectId.toString()).toBe(PROJECT_ID);
527
+ expect(memberCall.limit).toBe(LIMIT_PER_PROJECT);
528
+ expect(memberCall.skip).toBe(0);
529
+ expect(memberCall.select).toEqual({
530
+ _id: true,
531
+ user: { _id: true, name: true, email: true },
532
+ });
533
+
534
+ const teamCall: any = getListCallsFor(Team)[0];
535
+ expect(teamCall.query.projectId.toString()).toBe(PROJECT_ID);
536
+ expect(teamCall.limit).toBe(LIMIT_PER_PROJECT);
537
+ expect(teamCall.select).toEqual({ _id: true, name: true });
538
+ expect(teamCall.sort).toEqual({ name: SortOrder.Ascending });
539
+ });
540
+
541
+ test("fetches team members and teams in parallel", async () => {
542
+ getListMock.mockImplementation((listData: any): Promise<any> => {
543
+ if (listData.modelType === TeamMember) {
544
+ // Never settles, so the team read can only happen if it did not await this one.
545
+ return new Promise((): void => {});
546
+ }
547
+
548
+ return Promise.resolve({ data: [], count: 0, skip: 0, limit: 0 });
549
+ });
550
+
551
+ render(<Harness items={[]} />);
552
+
553
+ /*
554
+ * A project with a large membership table would otherwise hold the Teams
555
+ * group out of the dropdown for as long as that read takes.
556
+ */
557
+ await waitForOwnerSources();
558
+ expect(getListCallsFor(TeamMember)).toHaveLength(1);
559
+ expect(getListCallsFor(Team)).toHaveLength(1);
560
+ });
561
+
562
+ test("fetches nothing when there is no current project", async () => {
563
+ window.history.replaceState({}, "", "/dashboard");
564
+
565
+ render(<Harness items={[]} />);
566
+
567
+ await screen.findByText("Trigger Add Owner", {}, { timeout: WAIT_TIMEOUT });
568
+
569
+ /*
570
+ * Without the guard the query goes out with projectId undefined, which
571
+ * the API answers with every team member the caller can read.
572
+ */
573
+ expect(getListMock).not.toHaveBeenCalled();
574
+ });
575
+
576
+ test("lists a user once even when they are on several teams", async () => {
577
+ mockLists({
578
+ teamMembers: [
579
+ makeTeamMember({ userId: ALICE_ID, name: "Alice" }),
580
+ makeTeamMember({ userId: BOB_ID, name: "Bob" }),
581
+ makeTeamMember({ userId: ALICE_ID, name: "Alice" }),
582
+ ],
583
+ teams: [],
584
+ });
585
+
586
+ render(<Harness items={[]} />);
587
+ await waitForOwnerSources();
588
+ await openOwnerModal("Add Owner");
589
+ openOwnerMenu();
590
+
591
+ await screen.findByText("Bob", {}, { timeout: WAIT_TIMEOUT });
592
+ expect(screen.getAllByText("Alice")).toHaveLength(1);
593
+ });
594
+
595
+ test("sorts people case-insensitively by name", async () => {
596
+ mockLists({
597
+ teamMembers: [
598
+ makeTeamMember({ userId: CAROL_ID, name: "carol" }),
599
+ makeTeamMember({ userId: BOB_ID, name: "Bob" }),
600
+ makeTeamMember({ userId: ALICE_ID, name: "alice" }),
601
+ ],
602
+ teams: [],
603
+ });
604
+
605
+ render(<Harness items={[]} />);
606
+ await waitForOwnerSources();
607
+ await openOwnerModal("Add Owner");
608
+ openOwnerMenu();
609
+
610
+ await screen.findByText("alice", {}, { timeout: WAIT_TIMEOUT });
611
+
612
+ const optionLabels: Array<string> = screen
613
+ .getAllByRole("option")
614
+ .map((option: HTMLElement) => {
615
+ return option.textContent || "";
616
+ });
617
+
618
+ /*
619
+ * A plain codepoint sort puts every capitalised name ahead of every
620
+ * lowercase one, so "Bob" would jump the queue ahead of "alice".
621
+ */
622
+ expect(optionLabels).toEqual(["alice", "Bob", "carol"]);
623
+ });
624
+
625
+ test("falls back to a member's email when they have no name", async () => {
626
+ mockLists({
627
+ teamMembers: [
628
+ makeTeamMember({ userId: ALICE_ID, email: "alice@example.com" }),
629
+ ],
630
+ teams: [],
631
+ });
632
+
633
+ render(<Harness items={[]} />);
634
+ await waitForOwnerSources();
635
+ await openOwnerModal("Add Owner");
636
+ openOwnerMenu();
637
+
638
+ expect(
639
+ await screen.findByText(
640
+ "alice@example.com",
641
+ {},
642
+ { timeout: WAIT_TIMEOUT },
643
+ ),
644
+ ).toBeInTheDocument();
645
+ });
646
+
647
+ test("groups the options under People and Teams", async () => {
648
+ mockLists({
649
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
650
+ teams: [makeTeam(TEAM_ONE_ID, "Team One")],
651
+ });
652
+
653
+ render(<Harness items={[]} />);
654
+ await waitForOwnerSources();
655
+ await openOwnerModal("Add Owner");
656
+ openOwnerMenu();
657
+
658
+ expect(
659
+ await screen.findByText("People", {}, { timeout: WAIT_TIMEOUT }),
660
+ ).toBeInTheDocument();
661
+ expect(screen.getByText("Teams")).toBeInTheDocument();
662
+ expect(screen.getByText("Alice")).toBeInTheDocument();
663
+ expect(screen.getByText("Team One")).toBeInTheDocument();
664
+ });
665
+
666
+ test("offers every team in the project, in the order the API returned them", async () => {
667
+ mockLists({
668
+ teamMembers: [],
669
+ teams: [
670
+ makeTeam(TEAM_TWO_ID, "Zebra Team"),
671
+ makeTeam(TEAM_ONE_ID, "Apple Team"),
672
+ ],
673
+ });
674
+
675
+ render(<Harness items={[]} />);
676
+ await waitForOwnerSources();
677
+ await openOwnerModal("Add Owner");
678
+ openOwnerMenu();
679
+
680
+ await screen.findByText("Zebra Team", {}, { timeout: WAIT_TIMEOUT });
681
+
682
+ /*
683
+ * Teams keep the server's ordering (the query asks for name ASC); only
684
+ * the people list is re-sorted in the hook, because it is stitched
685
+ * together from every team's membership.
686
+ */
687
+ expect(
688
+ screen.getAllByRole("option").map((option: HTMLElement) => {
689
+ return option.textContent || "";
690
+ }),
691
+ ).toEqual(["Zebra Team", "Apple Team"]);
692
+ });
693
+
694
+ test("omits the People group when the project has no team members", async () => {
695
+ mockLists({
696
+ teamMembers: [],
697
+ teams: [makeTeam(TEAM_ONE_ID, "Team One")],
698
+ });
699
+
700
+ render(<Harness items={[]} />);
701
+ await waitForOwnerSources();
702
+ await openOwnerModal("Add Owner");
703
+ openOwnerMenu();
704
+
705
+ await screen.findByText("Teams", {}, { timeout: WAIT_TIMEOUT });
706
+
707
+ /*
708
+ * An empty group still renders its heading, so the dropdown would show a
709
+ * "People" label with nothing under it.
710
+ */
711
+ expect(screen.queryByText("People")).not.toBeInTheDocument();
712
+ });
713
+
714
+ test("omits the Teams group when the project has no teams", async () => {
715
+ mockLists({
716
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
717
+ teams: [],
718
+ });
719
+
720
+ render(<Harness items={[]} />);
721
+ await waitForOwnerSources();
722
+ await openOwnerModal("Add Owner");
723
+ openOwnerMenu();
724
+
725
+ await screen.findByText("People", {}, { timeout: WAIT_TIMEOUT });
726
+ expect(screen.queryByText("Teams")).not.toBeInTheDocument();
727
+ });
728
+
729
+ test("creates one owner row per picked user and per picked team", async () => {
730
+ mockLists({
731
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
732
+ teams: [makeTeam(TEAM_ONE_ID, "Team One")],
733
+ });
734
+
735
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
736
+ await waitForOwnerSources();
737
+ await openOwnerModal("Add Owner");
738
+ await selectOwner("Alice");
739
+ await selectOwner("Team One");
740
+ submitOwnerModal();
741
+
742
+ await waitFor(
743
+ () => {
744
+ expect(createMock).toHaveBeenCalledTimes(2);
745
+ },
746
+ { timeout: WAIT_TIMEOUT },
747
+ );
748
+
749
+ const userCall: any = (createMock.mock.calls[0] as Array<any>)[0];
750
+ expect(userCall.modelType).toBe(ServiceLevelObjectiveOwnerUser);
751
+ expect(userCall.model.userId.toString()).toBe(ALICE_ID);
752
+ expect(userCall.model.serviceLevelObjectiveId.toString()).toBe(SLO_ONE_ID);
753
+ expect(userCall.model.projectId.toString()).toBe(PROJECT_ID);
754
+
755
+ const teamCall: any = (createMock.mock.calls[1] as Array<any>)[0];
756
+ expect(teamCall.modelType).toBe(ServiceLevelObjectiveOwnerTeam);
757
+ expect(teamCall.model.teamId.toString()).toBe(TEAM_ONE_ID);
758
+ expect(teamCall.model.serviceLevelObjectiveId.toString()).toBe(SLO_ONE_ID);
759
+ expect(teamCall.model.projectId.toString()).toBe(PROJECT_ID);
760
+ });
761
+
762
+ test("creates a row for every selected item", async () => {
763
+ mockLists({
764
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
765
+ teams: [],
766
+ });
767
+
768
+ render(<Harness items={[makeSlo(SLO_ONE_ID), makeSlo(SLO_TWO_ID)]} />);
769
+ await waitForOwnerSources();
770
+ await openOwnerModal("Add Owner");
771
+ await selectOwner("Alice");
772
+ submitOwnerModal();
773
+
774
+ await waitFor(
775
+ () => {
776
+ expect(createMock).toHaveBeenCalledTimes(2);
777
+ },
778
+ { timeout: WAIT_TIMEOUT },
779
+ );
780
+
781
+ const resourceIds: Array<string> = (
782
+ createMock.mock.calls as Array<Array<any>>
783
+ ).map((call: Array<any>) => {
784
+ return call[0].model.serviceLevelObjectiveId.toString();
785
+ });
786
+
787
+ expect(resourceIds).toEqual([SLO_ONE_ID, SLO_TWO_ID]);
788
+ });
789
+
790
+ test("skips an owner the item already has", async () => {
791
+ mockLists({
792
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
793
+ teams: [makeTeam(TEAM_ONE_ID, "Team One")],
794
+ ownerUsers: [makeOwnerUserRow({ id: OWNER_ROW_ID, userId: ALICE_ID })],
795
+ ownerTeams: [],
796
+ });
797
+
798
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
799
+ await waitForOwnerSources();
800
+ await openOwnerModal("Add Owner");
801
+ await selectOwner("Alice");
802
+ await selectOwner("Team One");
803
+ submitOwnerModal();
804
+
805
+ await waitFor(
806
+ () => {
807
+ expect(createMock).toHaveBeenCalledTimes(1);
808
+ },
809
+ { timeout: WAIT_TIMEOUT },
810
+ );
811
+
812
+ /*
813
+ * Re-adding an existing owner is not a harmless duplicate: the owner
814
+ * lists on the resource render one row per junction record.
815
+ */
816
+ const onlyCall: any = (createMock.mock.calls[0] as Array<any>)[0];
817
+ expect(onlyCall.modelType).toBe(ServiceLevelObjectiveOwnerTeam);
818
+ });
819
+
820
+ test("reads the item's existing user owners with the resource-scoped query", async () => {
821
+ mockLists({
822
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
823
+ teams: [],
824
+ });
825
+
826
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
827
+ await waitForOwnerSources();
828
+ await openOwnerModal("Add Owner");
829
+ await selectOwner("Alice");
830
+ submitOwnerModal();
831
+
832
+ await waitFor(
833
+ () => {
834
+ expect(createMock).toHaveBeenCalledTimes(1);
835
+ },
836
+ { timeout: WAIT_TIMEOUT },
837
+ );
838
+
839
+ const ownerUserCall: any = getListCallsFor(
840
+ ServiceLevelObjectiveOwnerUser,
841
+ )[0];
842
+
843
+ /*
844
+ * The foreign key is a config string. Spelling it wrong compiles, and
845
+ * then this query matches every owner row in the project.
846
+ */
847
+ expect(ownerUserCall.query.serviceLevelObjectiveId.toString()).toBe(
848
+ SLO_ONE_ID,
849
+ );
850
+ expect(ownerUserCall.query.projectId.toString()).toBe(PROJECT_ID);
851
+ expect(ownerUserCall.select).toEqual({ userId: true });
852
+ expect(ownerUserCall.limit).toBe(LIMIT_PER_PROJECT);
853
+ expect(ownerUserCall.skip).toBe(0);
854
+ });
855
+
856
+ test("does not touch the team owner table when only a user was picked", async () => {
857
+ mockLists({
858
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
859
+ teams: [makeTeam(TEAM_ONE_ID, "Team One")],
860
+ });
861
+
862
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
863
+ await waitForOwnerSources();
864
+ await openOwnerModal("Add Owner");
865
+ await selectOwner("Alice");
866
+ submitOwnerModal();
867
+
868
+ await waitFor(
869
+ () => {
870
+ expect(createMock).toHaveBeenCalledTimes(1);
871
+ },
872
+ { timeout: WAIT_TIMEOUT },
873
+ );
874
+
875
+ expect(getListCallsFor(ServiceLevelObjectiveOwnerUser)).toHaveLength(1);
876
+ expect(getListCallsFor(ServiceLevelObjectiveOwnerTeam)).toHaveLength(0);
877
+ });
878
+
879
+ test("does not touch the user owner table when only a team was picked", async () => {
880
+ mockLists({
881
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
882
+ teams: [makeTeam(TEAM_ONE_ID, "Team One")],
883
+ });
884
+
885
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
886
+ await waitForOwnerSources();
887
+ await openOwnerModal("Add Owner");
888
+ await selectOwner("Team One");
889
+ submitOwnerModal();
890
+
891
+ await waitFor(
892
+ () => {
893
+ expect(createMock).toHaveBeenCalledTimes(1);
894
+ },
895
+ { timeout: WAIT_TIMEOUT },
896
+ );
897
+
898
+ expect(getListCallsFor(ServiceLevelObjectiveOwnerTeam)).toHaveLength(1);
899
+ expect(getListCallsFor(ServiceLevelObjectiveOwnerUser)).toHaveLength(0);
900
+ });
901
+
902
+ test("deletes the junction rows that match the removed owners", async () => {
903
+ mockLists({
904
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
905
+ teams: [makeTeam(TEAM_ONE_ID, "Team One")],
906
+ ownerUsers: [makeOwnerUserRow({ id: OWNER_ROW_ID, userId: ALICE_ID })],
907
+ ownerTeams: [
908
+ makeOwnerTeamRow({ id: OWNER_ROW_TWO_ID, teamId: TEAM_ONE_ID }),
909
+ ],
910
+ });
911
+
912
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
913
+ await waitForOwnerSources();
914
+ await openOwnerModal("Remove Owner");
915
+ await selectOwner("Alice");
916
+ await selectOwner("Team One");
917
+ submitOwnerModal();
918
+
919
+ await waitFor(
920
+ () => {
921
+ expect(deleteItemMock).toHaveBeenCalledTimes(2);
922
+ },
923
+ { timeout: WAIT_TIMEOUT },
924
+ );
925
+
926
+ const userDelete: any = (deleteItemMock.mock.calls[0] as Array<any>)[0];
927
+ expect(userDelete.modelType).toBe(ServiceLevelObjectiveOwnerUser);
928
+ expect(userDelete.id.toString()).toBe(OWNER_ROW_ID);
929
+
930
+ const teamDelete: any = (deleteItemMock.mock.calls[1] as Array<any>)[0];
931
+ expect(teamDelete.modelType).toBe(ServiceLevelObjectiveOwnerTeam);
932
+ expect(teamDelete.id.toString()).toBe(OWNER_ROW_TWO_ID);
933
+
934
+ expect(createMock).not.toHaveBeenCalled();
935
+ });
936
+
937
+ test("looks the removable rows up by the selected owner ids", async () => {
938
+ mockLists({
939
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
940
+ teams: [],
941
+ ownerUsers: [makeOwnerUserRow({ id: OWNER_ROW_ID, userId: ALICE_ID })],
942
+ });
943
+
944
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
945
+ await waitForOwnerSources();
946
+ await openOwnerModal("Remove Owner");
947
+ await selectOwner("Alice");
948
+ submitOwnerModal();
949
+
950
+ await waitFor(
951
+ () => {
952
+ expect(deleteItemMock).toHaveBeenCalledTimes(1);
953
+ },
954
+ { timeout: WAIT_TIMEOUT },
955
+ );
956
+
957
+ const lookup: any = getListCallsFor(ServiceLevelObjectiveOwnerUser)[0];
958
+ expect(lookup.query.serviceLevelObjectiveId.toString()).toBe(SLO_ONE_ID);
959
+ expect(lookup.query.userId).toBeInstanceOf(Includes);
960
+ expect(
961
+ (lookup.query.userId.values as Array<ObjectID>).map((id: ObjectID) => {
962
+ return id.toString();
963
+ }),
964
+ ).toEqual([ALICE_ID]);
965
+ expect(lookup.select).toEqual({ _id: true });
966
+ });
967
+
968
+ test("skips a junction row that came back without an id", async () => {
969
+ mockLists({
970
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
971
+ teams: [],
972
+ ownerUsers: [
973
+ makeOwnerUserRow({ userId: ALICE_ID }),
974
+ makeOwnerUserRow({ id: OWNER_ROW_ID, userId: ALICE_ID }),
975
+ ],
976
+ });
977
+
978
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
979
+ await waitForOwnerSources();
980
+ await openOwnerModal("Remove Owner");
981
+ await selectOwner("Alice");
982
+ submitOwnerModal();
983
+
984
+ await waitFor(
985
+ () => {
986
+ expect(onBulkActionEnd).toHaveBeenCalledTimes(1);
987
+ },
988
+ { timeout: WAIT_TIMEOUT },
989
+ );
990
+
991
+ /*
992
+ * A select that drops _id would otherwise send DELETE with an undefined
993
+ * id, which the API resolves to "delete by query".
994
+ */
995
+ expect(deleteItemMock).toHaveBeenCalledTimes(1);
996
+ expect((deleteItemMock.mock.calls[0] as Array<any>)[0].id.toString()).toBe(
997
+ OWNER_ROW_ID,
998
+ );
999
+ });
1000
+
1001
+ test("counts an item that has none of the removed owners as a success", async () => {
1002
+ mockLists({
1003
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
1004
+ teams: [],
1005
+ ownerUsers: [],
1006
+ });
1007
+
1008
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
1009
+ await waitForOwnerSources();
1010
+ await openOwnerModal("Remove Owner");
1011
+ await selectOwner("Alice");
1012
+ submitOwnerModal();
1013
+
1014
+ await waitFor(
1015
+ () => {
1016
+ expect(onBulkActionEnd).toHaveBeenCalledTimes(1);
1017
+ },
1018
+ { timeout: WAIT_TIMEOUT },
1019
+ );
1020
+
1021
+ expect(deleteItemMock).not.toHaveBeenCalled();
1022
+ expect(progressSnapshots).toHaveLength(1);
1023
+ expect(progressSnapshots[0]!.successItems).toEqual([SLO_ONE_ID]);
1024
+ expect(progressSnapshots[0]!.failed).toEqual([]);
1025
+ });
1026
+
1027
+ test("keeps going after one item fails and reports why", async () => {
1028
+ mockLists({
1029
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
1030
+ teams: [],
1031
+ });
1032
+
1033
+ createMock.mockImplementation(async (data: any): Promise<any> => {
1034
+ if (data.model.serviceLevelObjectiveId.toString() === SLO_ONE_ID) {
1035
+ throw new BadDataException("Owner could not be added");
1036
+ }
1037
+
1038
+ return {};
1039
+ });
1040
+
1041
+ render(<Harness items={[makeSlo(SLO_ONE_ID), makeSlo(SLO_TWO_ID)]} />);
1042
+ await waitForOwnerSources();
1043
+ await openOwnerModal("Add Owner");
1044
+ await selectOwner("Alice");
1045
+ submitOwnerModal();
1046
+
1047
+ await waitFor(
1048
+ () => {
1049
+ expect(onBulkActionEnd).toHaveBeenCalledTimes(1);
1050
+ },
1051
+ { timeout: WAIT_TIMEOUT },
1052
+ );
1053
+
1054
+ const finalSnapshot: ProgressSnapshot = progressSnapshots[1]!;
1055
+ expect(finalSnapshot.successItems).toEqual([SLO_TWO_ID]);
1056
+ expect(finalSnapshot.failed).toEqual([
1057
+ { id: SLO_ONE_ID, failedMessage: "Owner could not be added" },
1058
+ ]);
1059
+ });
1060
+
1061
+ test("fails an item with no id without calling the API for it", async () => {
1062
+ mockLists({
1063
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
1064
+ teams: [],
1065
+ });
1066
+
1067
+ render(<Harness items={[makeSlo(), makeSlo(SLO_ONE_ID)]} />);
1068
+ await waitForOwnerSources();
1069
+ await openOwnerModal("Add Owner");
1070
+ await selectOwner("Alice");
1071
+ submitOwnerModal();
1072
+
1073
+ await waitFor(
1074
+ () => {
1075
+ expect(onBulkActionEnd).toHaveBeenCalledTimes(1);
1076
+ },
1077
+ { timeout: WAIT_TIMEOUT },
1078
+ );
1079
+
1080
+ const finalSnapshot: ProgressSnapshot = progressSnapshots[1]!;
1081
+ expect(finalSnapshot.failed).toEqual([
1082
+ { id: "no-id", failedMessage: "Item ID not found" },
1083
+ ]);
1084
+ expect(finalSnapshot.successItems).toEqual([SLO_ONE_ID]);
1085
+
1086
+ /*
1087
+ * An id-less item must not reach the junction query: with the resource
1088
+ * id missing the filter collapses to the whole project.
1089
+ */
1090
+ expect(getListCallsFor(ServiceLevelObjectiveOwnerUser)).toHaveLength(1);
1091
+ expect(createMock).toHaveBeenCalledTimes(1);
1092
+ });
1093
+
1094
+ test("fails every item when the project is gone by the time the form is submitted", async () => {
1095
+ mockLists({
1096
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
1097
+ teams: [],
1098
+ });
1099
+
1100
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
1101
+ await waitForOwnerSources();
1102
+ await openOwnerModal("Add Owner");
1103
+ await selectOwner("Alice");
1104
+
1105
+ window.history.replaceState({}, "", "/dashboard");
1106
+
1107
+ submitOwnerModal();
1108
+
1109
+ await waitFor(
1110
+ () => {
1111
+ expect(onBulkActionEnd).toHaveBeenCalledTimes(1);
1112
+ },
1113
+ { timeout: WAIT_TIMEOUT },
1114
+ );
1115
+
1116
+ expect(progressSnapshots[0]!.failed).toEqual([
1117
+ { id: SLO_ONE_ID, failedMessage: "Project not found" },
1118
+ ]);
1119
+ expect(createMock).not.toHaveBeenCalled();
1120
+ });
1121
+
1122
+ test("brackets the run with onBulkActionStart and onBulkActionEnd", async () => {
1123
+ mockLists({
1124
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
1125
+ teams: [],
1126
+ });
1127
+
1128
+ render(<Harness items={[makeSlo(SLO_ONE_ID), makeSlo(SLO_TWO_ID)]} />);
1129
+ await waitForOwnerSources();
1130
+ await openOwnerModal("Add Owner");
1131
+ await selectOwner("Alice");
1132
+ submitOwnerModal();
1133
+
1134
+ await waitFor(
1135
+ () => {
1136
+ expect(onBulkActionEnd).toHaveBeenCalledTimes(1);
1137
+ },
1138
+ { timeout: WAIT_TIMEOUT },
1139
+ );
1140
+
1141
+ expect(onBulkActionStart).toHaveBeenCalledTimes(1);
1142
+ expect(onProgressInfo).toHaveBeenCalledTimes(2);
1143
+ expect(onBulkActionStart.mock.invocationCallOrder[0]!).toBeLessThan(
1144
+ onProgressInfo.mock.invocationCallOrder[0]!,
1145
+ );
1146
+ expect(onBulkActionEnd.mock.invocationCallOrder[0]!).toBeGreaterThan(
1147
+ onProgressInfo.mock.invocationCallOrder[1]!,
1148
+ );
1149
+ });
1150
+
1151
+ test("moves each item from in-progress to success as it is processed", async () => {
1152
+ mockLists({
1153
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
1154
+ teams: [],
1155
+ });
1156
+
1157
+ render(<Harness items={[makeSlo(SLO_ONE_ID), makeSlo(SLO_TWO_ID)]} />);
1158
+ await waitForOwnerSources();
1159
+ await openOwnerModal("Add Owner");
1160
+ await selectOwner("Alice");
1161
+ submitOwnerModal();
1162
+
1163
+ await waitFor(
1164
+ () => {
1165
+ expect(onBulkActionEnd).toHaveBeenCalledTimes(1);
1166
+ },
1167
+ { timeout: WAIT_TIMEOUT },
1168
+ );
1169
+
1170
+ /*
1171
+ * The item being worked on is spliced out of inProgressItems before its
1172
+ * own callback fires, so the progress bar never double-counts it.
1173
+ */
1174
+ expect(progressSnapshots).toEqual([
1175
+ {
1176
+ totalItems: [SLO_ONE_ID, SLO_TWO_ID],
1177
+ inProgressItems: [SLO_TWO_ID],
1178
+ successItems: [SLO_ONE_ID],
1179
+ failed: [],
1180
+ },
1181
+ {
1182
+ totalItems: [SLO_ONE_ID, SLO_TWO_ID],
1183
+ inProgressItems: [],
1184
+ successItems: [SLO_ONE_ID, SLO_TWO_ID],
1185
+ failed: [],
1186
+ },
1187
+ ]);
1188
+ });
1189
+
1190
+ test("opening Add Owner closes an open Remove Owner modal", async () => {
1191
+ mockLists({
1192
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
1193
+ teams: [],
1194
+ });
1195
+
1196
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
1197
+ await waitForOwnerSources();
1198
+ await openOwnerModal("Remove Owner");
1199
+ clickOwnerAction("Add Owner");
1200
+
1201
+ const openTitles: Array<HTMLElement> = screen.getAllByTestId("modal-title");
1202
+
1203
+ /*
1204
+ * Both dialogs share one bulkActionProps, and the first submit nulls it -
1205
+ * so a second one left stacked behind would swallow its own submit.
1206
+ */
1207
+ expect(openTitles).toHaveLength(1);
1208
+ expect(openTitles[0]!).toHaveTextContent("Add Owner");
1209
+ });
1210
+
1211
+ test("opening Remove Owner closes an open Add Owner modal", async () => {
1212
+ mockLists({
1213
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
1214
+ teams: [],
1215
+ });
1216
+
1217
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
1218
+ await waitForOwnerSources();
1219
+ await openOwnerModal("Add Owner");
1220
+ clickOwnerAction("Remove Owner");
1221
+
1222
+ const openTitles: Array<HTMLElement> = screen.getAllByTestId("modal-title");
1223
+
1224
+ expect(openTitles).toHaveLength(1);
1225
+ expect(openTitles[0]!).toHaveTextContent("Remove Owner");
1226
+ });
1227
+
1228
+ test("blocks a submit with nothing selected", async () => {
1229
+ mockLists({
1230
+ teamMembers: [makeTeamMember({ userId: ALICE_ID, name: "Alice" })],
1231
+ teams: [makeTeam(TEAM_ONE_ID, "Team One")],
1232
+ });
1233
+
1234
+ render(<Harness items={[makeSlo(SLO_ONE_ID)]} />);
1235
+ await waitForOwnerSources();
1236
+ await openOwnerModal("Add Owner");
1237
+ submitOwnerModal();
1238
+
1239
+ expect(
1240
+ await screen.findByText(
1241
+ "Select Owners is required.",
1242
+ {},
1243
+ { timeout: WAIT_TIMEOUT },
1244
+ ),
1245
+ ).toBeInTheDocument();
1246
+
1247
+ /*
1248
+ * Without the required rule an empty submit still walks every selected
1249
+ * item, reporting a batch of successes that changed nothing.
1250
+ */
1251
+ expect(createMock).not.toHaveBeenCalled();
1252
+ expect(onBulkActionStart).not.toHaveBeenCalled();
1253
+ expect(getListMock).toHaveBeenCalledTimes(2);
1254
+ });
1255
+ });