@oneuptime/common 14.0.10 → 14.0.11

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 (837) hide show
  1. package/Models/DatabaseModels/AIConversation.ts +127 -1
  2. package/Models/DatabaseModels/CephCluster.ts +12 -0
  3. package/Models/DatabaseModels/CloudResource.ts +12 -0
  4. package/Models/DatabaseModels/DatabaseServer.ts +12 -0
  5. package/Models/DatabaseModels/DockerHost.ts +12 -0
  6. package/Models/DatabaseModels/DockerSwarmCluster.ts +12 -0
  7. package/Models/DatabaseModels/GlobalOidc.ts +0 -4
  8. package/Models/DatabaseModels/GlobalOidcProject.ts +0 -4
  9. package/Models/DatabaseModels/GlobalSso.ts +0 -4
  10. package/Models/DatabaseModels/GlobalSsoProject.ts +0 -4
  11. package/Models/DatabaseModels/Host.ts +12 -0
  12. package/Models/DatabaseModels/IncidentForm.ts +594 -0
  13. package/Models/DatabaseModels/IncidentFormSubmission.ts +283 -0
  14. package/Models/DatabaseModels/IncidentTemplate.ts +59 -0
  15. package/Models/DatabaseModels/Index.ts +14 -0
  16. package/Models/DatabaseModels/IoTFleet.ts +12 -0
  17. package/Models/DatabaseModels/KubernetesCluster.ts +12 -0
  18. package/Models/DatabaseModels/MessageQueue.ts +1102 -0
  19. package/Models/DatabaseModels/MessageQueueLabelRule.ts +553 -0
  20. package/Models/DatabaseModels/MessageQueueOwnerRule.ts +633 -0
  21. package/Models/DatabaseModels/MessageQueueOwnerTeam.ts +491 -0
  22. package/Models/DatabaseModels/MessageQueueOwnerUser.ts +490 -0
  23. package/Models/DatabaseModels/PodmanHost.ts +12 -0
  24. package/Models/DatabaseModels/Project.ts +59 -0
  25. package/Models/DatabaseModels/ProjectOidc.ts +0 -4
  26. package/Models/DatabaseModels/ProjectSso.ts +0 -4
  27. package/Models/DatabaseModels/ProxmoxCluster.ts +12 -0
  28. package/Models/DatabaseModels/RumApplication.ts +12 -0
  29. package/Models/DatabaseModels/ServerlessFunction.ts +12 -0
  30. package/Models/DatabaseModels/Service.ts +12 -0
  31. package/Models/DatabaseModels/StatusPageOidc.ts +0 -4
  32. package/Models/DatabaseModels/StatusPageSso.ts +0 -4
  33. package/Models/DatabaseModels/TeamComplianceSetting.ts +47 -2
  34. package/Models/DatabaseModels/VMwareVCenter.ts +12 -0
  35. package/Server/API/AIChatAPI.ts +13 -114
  36. package/Server/API/AIInvestigationAPI.ts +3 -3
  37. package/Server/API/AIInvestigationConversationAPI.ts +266 -0
  38. package/Server/API/IncidentFormAPI.ts +376 -0
  39. package/Server/API/ProjectOIDC.ts +16 -25
  40. package/Server/API/ProjectSSO.ts +16 -24
  41. package/Server/API/StatusPageAPI.ts +42 -77
  42. package/Server/Enterprise/EnterpriseEdition.ts +93 -28
  43. package/Server/Enterprise/EnterpriseFeature.ts +25 -3
  44. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +1 -1
  45. package/Server/Enterprise/EnterpriseServerModule.ts +4 -1
  46. package/Server/EnvironmentConfig.ts +1 -1
  47. package/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.ts +129 -0
  48. package/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.ts +52 -0
  49. package/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.ts +75 -0
  50. package/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.ts +477 -0
  51. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  52. package/Server/Middleware/IncidentFormRateLimit.ts +847 -0
  53. package/Server/Middleware/UserAuthorization.ts +16 -38
  54. package/Server/Services/AIService.ts +10 -13
  55. package/Server/Services/IncidentCustomFieldService.ts +112 -2
  56. package/Server/Services/IncidentEpisodeMemberService.ts +24 -4
  57. package/Server/Services/IncidentEpisodeService.ts +10 -1
  58. package/Server/Services/IncidentFormService.ts +1566 -0
  59. package/Server/Services/IncidentFormSubmissionService.ts +97 -0
  60. package/Server/Services/IncidentGroupingEngineService.ts +45 -8
  61. package/Server/Services/IncidentService.ts +123 -5
  62. package/Server/Services/IncidentTemplateService.ts +22 -0
  63. package/Server/Services/Index.ts +14 -0
  64. package/Server/Services/MessageQueueLabelRuleEngineService.ts +321 -0
  65. package/Server/Services/MessageQueueLabelRuleService.ts +14 -0
  66. package/Server/Services/MessageQueueOwnerRuleEngineService.ts +412 -0
  67. package/Server/Services/MessageQueueOwnerRuleService.ts +14 -0
  68. package/Server/Services/MessageQueueOwnerTeamService.ts +62 -0
  69. package/Server/Services/MessageQueueOwnerUserService.ts +62 -0
  70. package/Server/Services/MessageQueueService.ts +1463 -0
  71. package/Server/Services/OpenTelemetryIngestService.ts +37 -4
  72. package/Server/Services/ProjectService.ts +0 -59
  73. package/Server/Services/StatusPagePrivateUserService.ts +1 -4
  74. package/Server/Services/StatusPageService.ts +1 -51
  75. package/Server/Services/TeamComplianceSettingService.ts +163 -42
  76. package/Server/Services/UserNotificationRuleService.ts +8 -1
  77. package/Server/Services/WorkspaceNotificationSummaryService.ts +12 -3
  78. package/Server/Types/Database/Permissions/CreatePermission.ts +17 -3
  79. package/Server/Types/Database/Permissions/EditionPermission.ts +140 -38
  80. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +16 -0
  81. package/Server/Types/Database/Permissions/TablePermission.ts +3 -3
  82. package/Server/Types/Database/Permissions/UpdatePermission.ts +20 -6
  83. package/Server/Utils/AI/Chat/AgentContextCompactor.ts +200 -0
  84. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +307 -48
  85. package/Server/Utils/AI/Chat/ChatRunCancellation.ts +156 -0
  86. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +78 -18
  87. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
  88. package/Server/Utils/AI/Chat/ToolOutputPager.ts +322 -0
  89. package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +88 -30
  90. package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +13 -1
  91. package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +0 -32
  92. package/Server/Utils/AI/CodeFix/FixRunBudget.ts +27 -25
  93. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +7 -1
  94. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +34 -14
  95. package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +69 -24
  96. package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +9 -0
  97. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +53 -10
  98. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +27 -10
  99. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +27 -10
  100. package/Server/Utils/AI/SRE/InvestigationQueue.ts +16 -19
  101. package/Server/Utils/AI/SRE/InvestigationThread.ts +646 -0
  102. package/Server/Utils/AI/SRE/InvestigationThreadService.ts +715 -0
  103. package/Server/Utils/AI/Toolbox/Serializer.ts +10 -3
  104. package/Server/Utils/EditionEnforcement.ts +19 -202
  105. package/Server/Utils/LLM/LLMService.ts +259 -63
  106. package/Server/Utils/RelaxedScimTeamLocksReport.ts +245 -0
  107. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
  108. package/Server/Utils/SameOriginRequest.ts +203 -0
  109. package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
  110. package/Server/Utils/Telemetry/EntityRegistry.ts +4 -1
  111. package/Server/Utils/Telemetry/MessageQueueDiscovery.ts +1402 -0
  112. package/Server/Utils/Telemetry/ResourceEntityFilter.ts +4 -1
  113. package/Server/Utils/VendorAssets.ts +3 -3
  114. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +3 -1
  115. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +3 -1
  116. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +10 -1
  117. package/Tests/App/Accounts/IncidentFormPage.test.tsx +2036 -0
  118. package/Tests/App/Accounts/IncidentFormServerMessages.test.ts +119 -0
  119. package/Tests/App/Accounts/IncidentFormUtils.test.ts +1157 -0
  120. package/Tests/App/Accounts/LoginPasskey.test.tsx +6 -4
  121. package/Tests/App/Accounts/LoginSso.test.tsx +724 -0
  122. package/Tests/App/AdminDashboard/AdminAuthenticationRequireSso.test.tsx +338 -0
  123. package/Tests/App/AdminDashboard/AdminAuthenticationSsoCardLocales.test.tsx +331 -0
  124. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +47 -33
  125. package/Tests/App/AdminDashboard/GlobalSsoOidcPages.test.tsx +1021 -0
  126. package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +876 -78
  127. package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +20 -3
  128. package/Tests/App/Dashboard/CephProxmoxVMwareDocumentationCards.test.tsx +359 -0
  129. package/Tests/App/Dashboard/CephSetupGuide.test.ts +961 -0
  130. package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +381 -95
  131. package/Tests/App/Dashboard/CloudSetupGuide.test.ts +1463 -0
  132. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +174 -12
  133. package/Tests/App/Dashboard/ContainerSetupGuideCards.test.tsx +345 -0
  134. package/Tests/App/Dashboard/CoreListEmptyStates.test.tsx +501 -0
  135. package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +0 -1
  136. package/Tests/App/Dashboard/DatabaseDocumentationCard.test.tsx +400 -0
  137. package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +5 -0
  138. package/Tests/App/Dashboard/DatabaseSetupGuide.test.ts +1869 -0
  139. package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +44 -0
  140. package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +50 -9
  141. package/Tests/App/Dashboard/DockerSetupGuide.test.ts +899 -0
  142. package/Tests/App/Dashboard/DockerSwarmSetupGuide.test.ts +964 -0
  143. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +141 -7
  144. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +52 -39
  145. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +7 -1
  146. package/Tests/App/Dashboard/GettingStartedTaskRoutes.test.tsx +331 -0
  147. package/Tests/App/Dashboard/HomeOverviewStatsFirstRun.test.tsx +925 -0
  148. package/Tests/App/Dashboard/HostDocumentationCard.test.tsx +225 -0
  149. package/Tests/App/Dashboard/HostSetupGuide.test.ts +1183 -0
  150. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +69 -45
  151. package/Tests/App/Dashboard/IncidentCreateTemplateCustomFieldSettings.test.tsx +745 -0
  152. package/Tests/App/Dashboard/IncidentCreateTemplateOwners.test.tsx +414 -0
  153. package/Tests/App/Dashboard/IncidentCustomFieldCreateSettingsForm.test.ts +1042 -0
  154. package/Tests/App/Dashboard/IncidentCustomFieldSettingsCard.test.tsx +1816 -0
  155. package/Tests/App/Dashboard/IncidentFormPlan.test.ts +89 -0
  156. package/Tests/App/Dashboard/IncidentFormShareLinkCard.test.tsx +846 -0
  157. package/Tests/App/Dashboard/IncidentFormsPages.test.tsx +1324 -0
  158. package/Tests/App/Dashboard/IncidentTemplateCustomFieldSettings.test.tsx +630 -0
  159. package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +13 -0
  160. package/Tests/App/Dashboard/IncomingEmailMonitorLinkVerifyHint.test.tsx +104 -0
  161. package/Tests/App/Dashboard/InvestigationConversation.test.tsx +1107 -0
  162. package/Tests/App/Dashboard/InvestigationConversationData.test.ts +546 -0
  163. package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +170 -5
  164. package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +207 -2
  165. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +729 -34
  166. package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +9 -21
  167. package/Tests/App/Dashboard/InvestigationReportView.test.tsx +274 -37
  168. package/Tests/App/Dashboard/InvestigationStatusBadge.test.tsx +130 -0
  169. package/Tests/App/Dashboard/IoTDocumentationCard.test.tsx +218 -0
  170. package/Tests/App/Dashboard/IoTSetupGuide.test.ts +1124 -0
  171. package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +20 -6
  172. package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +107 -83
  173. package/Tests/App/Dashboard/KubernetesSetupGuide.test.ts +787 -0
  174. package/Tests/App/Dashboard/MessageQueueBreadcrumbs.test.tsx +228 -0
  175. package/Tests/App/Dashboard/MessageQueueBrokerHealth.test.tsx +1538 -0
  176. package/Tests/App/Dashboard/MessageQueueBrokerHealthMetricChart.test.tsx +969 -0
  177. package/Tests/App/Dashboard/MessageQueueBrokerHealthReads.test.ts +889 -0
  178. package/Tests/App/Dashboard/MessageQueueBrokerMetricsReach.test.ts +236 -0
  179. package/Tests/App/Dashboard/MessageQueueDocumentationCard.test.tsx +479 -0
  180. package/Tests/App/Dashboard/MessageQueueListPages.test.tsx +1232 -0
  181. package/Tests/App/Dashboard/MessageQueueMetricDescriptions.test.ts +244 -0
  182. package/Tests/App/Dashboard/MessageQueueMonitorLink.test.ts +952 -0
  183. package/Tests/App/Dashboard/MessageQueueMonitorLinkMonitorCreate.test.tsx +859 -0
  184. package/Tests/App/Dashboard/MessageQueueOverview.test.tsx +1773 -0
  185. package/Tests/App/Dashboard/MessageQueueOverviewPresentation.test.ts +196 -0
  186. package/Tests/App/Dashboard/MessageQueuePresentation.test.ts +799 -0
  187. package/Tests/App/Dashboard/MessageQueueProducersConsumers.test.tsx +680 -0
  188. package/Tests/App/Dashboard/MessageQueueRoutes.test.tsx +383 -0
  189. package/Tests/App/Dashboard/MessageQueueRulePages.test.tsx +278 -0
  190. package/Tests/App/Dashboard/MessageQueueSetupGuide.test.ts +2778 -0
  191. package/Tests/App/Dashboard/MessageQueueSideMenus.test.tsx +273 -0
  192. package/Tests/App/Dashboard/MessageQueueSpanPopulations.test.ts +930 -0
  193. package/Tests/App/Dashboard/MessageQueueSpanStore.ts +351 -0
  194. package/Tests/App/Dashboard/MessageQueueTelemetryScope.test.ts +375 -0
  195. package/Tests/App/Dashboard/MessageQueueTelemetryScopeTabs.test.tsx +668 -0
  196. package/Tests/App/Dashboard/MessageQueueViewPages.test.tsx +685 -0
  197. package/Tests/App/Dashboard/MonitorAndHomeNotOperationalMenus.test.tsx +342 -0
  198. package/Tests/App/Dashboard/MonitorCreateFirstRunDefaults.test.tsx +623 -0
  199. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +442 -0
  200. package/Tests/App/Dashboard/MonitorLogsPageViewSummary.test.tsx +814 -0
  201. package/Tests/App/Dashboard/MonitorSetupCardBodies.test.tsx +246 -0
  202. package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +8 -0
  203. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +27 -12
  204. package/Tests/App/Dashboard/PlanGatedPage.test.tsx +292 -0
  205. package/Tests/App/Dashboard/PodmanSetupGuide.test.ts +948 -0
  206. package/Tests/App/Dashboard/ProductOrientation.test.tsx +5 -4
  207. package/Tests/App/Dashboard/ProductSettingsSectionCollapsed.test.tsx +266 -0
  208. package/Tests/App/Dashboard/ProxmoxSetupGuide.test.ts +1318 -0
  209. package/Tests/App/Dashboard/ResourceAiAgentAttentionServerParity.test.ts +555 -0
  210. package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +298 -9
  211. package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +453 -0
  212. package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +16 -0
  213. package/Tests/App/Dashboard/ResourceConnectionGuideCard.test.tsx +444 -0
  214. package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsInfra.test.tsx +798 -0
  215. package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsPlatforms.test.tsx +717 -0
  216. package/Tests/App/Dashboard/ResourceConnectionGuides.test.ts +981 -0
  217. package/Tests/App/Dashboard/ResourceConnectionState.test.ts +132 -0
  218. package/Tests/App/Dashboard/RumDocumentationCard.test.tsx +293 -0
  219. package/Tests/App/Dashboard/RumSessionReplayRetentionSettings.test.tsx +467 -0
  220. package/Tests/App/Dashboard/RumSetupGuide.test.ts +758 -0
  221. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +25 -0
  222. package/Tests/App/Dashboard/ServerlessDocumentationCard.test.tsx +254 -0
  223. package/Tests/App/Dashboard/ServerlessSetupGuide.test.ts +1074 -0
  224. package/Tests/App/Dashboard/SetupGuide.test.ts +246 -0
  225. package/Tests/App/Dashboard/SetupGuideCard.test.tsx +756 -0
  226. package/Tests/App/Dashboard/SloListSideMenu.test.tsx +120 -0
  227. package/Tests/App/Dashboard/SsoPages.test.tsx +833 -0
  228. package/Tests/App/Dashboard/TelemetryDocumentation.test.tsx +253 -0
  229. package/Tests/App/Dashboard/TelemetryRetentionShells.test.tsx +730 -0
  230. package/Tests/App/Dashboard/VMwareSetupGuide.test.ts +1033 -0
  231. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +87 -7
  232. package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +28 -9
  233. package/Tests/Models/DatabaseModels/IncidentFormModel.test.ts +1250 -0
  234. package/Tests/Models/DatabaseModels/MessageQueueModels.test.ts +1983 -0
  235. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  236. package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +190 -14
  237. package/Tests/Models/IncidentTemplateCustomFieldSettingsColumn.test.ts +291 -0
  238. package/Tests/Server/API/AIInvestigationConversationAPI.test.ts +412 -0
  239. package/Tests/Server/API/GlobalConfigLicense.test.ts +38 -9
  240. package/Tests/Server/API/IncidentFormAPI.test.ts +942 -0
  241. package/Tests/Server/API/IncidentFormPublicRoutes.test.ts +1653 -0
  242. package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -1
  243. package/Tests/Server/API/{SsoProviderListingsEdition.test.ts → SsoProviderListings.test.ts} +164 -110
  244. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +76 -54
  245. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +125 -42
  246. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +36 -10
  247. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +51 -9
  248. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +13 -8
  249. package/Tests/Server/Enterprise/SsoInCommunityEdition.test.ts +540 -0
  250. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  251. package/Tests/Server/Infrastructure/Postgres/AddIncidentFormsMigration.test.ts +438 -0
  252. package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleNotificationChannelsMigration.test.ts +255 -0
  253. package/Tests/Server/Infrastructure/Postgres/MessageQueueTablesMigration.test.ts +637 -0
  254. package/Tests/Server/Middleware/IncidentFormRateLimit.test.ts +1630 -0
  255. package/Tests/Server/Middleware/UserAuthorization.test.ts +16 -17
  256. package/Tests/Server/Middleware/UserAuthorizationSsoEnforcement.test.ts +544 -0
  257. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +37 -8
  258. package/Tests/Server/Services/IncidentCreatedFeedTitle.test.ts +212 -0
  259. package/Tests/Server/Services/IncidentCustomFieldDeleteFormQuestions.test.ts +297 -0
  260. package/Tests/Server/Services/IncidentFormOwnersCreatedNotification.test.ts +497 -0
  261. package/Tests/Server/Services/IncidentFormPostgres.test.ts +958 -0
  262. package/Tests/Server/Services/IncidentFormPublicForm.test.ts +1260 -0
  263. package/Tests/Server/Services/IncidentFormPublicSubmission.test.ts +2520 -0
  264. package/Tests/Server/Services/IncidentFormRegistration.test.ts +159 -0
  265. package/Tests/Server/Services/IncidentFormService.test.ts +663 -0
  266. package/Tests/Server/Services/IncidentFormSubmissionService.test.ts +430 -0
  267. package/Tests/Server/Services/IncidentFormSubmissionTemplateBranch.test.ts +473 -0
  268. package/Tests/Server/Services/IncidentGroupingTemplateSubstitution.test.ts +81 -0
  269. package/Tests/Server/Services/IncidentTemplateCustomFieldSettings.test.ts +262 -0
  270. package/Tests/Server/Services/IncidentTemplateOwnersOnDeclare.test.ts +566 -0
  271. package/Tests/Server/Services/IncidentTitleMarkdownSinks.test.ts +640 -0
  272. package/Tests/Server/Services/LlmLogServiceTokenAggregateParams.test.ts +3 -3
  273. package/Tests/Server/Services/MessageQueueOwnerServices.test.ts +440 -0
  274. package/Tests/Server/Services/MessageQueueRegistries.test.ts +577 -0
  275. package/Tests/Server/Services/MessageQueueRuleEngines.test.ts +900 -0
  276. package/Tests/Server/Services/MessageQueueService.test.ts +2210 -0
  277. package/Tests/Server/Services/MessageQueueSqlPostgres.test.ts +1271 -0
  278. package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
  279. package/Tests/Server/Services/OpenTelemetryRetentionOverrideEdition.test.ts +474 -0
  280. package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +21 -0
  281. package/Tests/Server/Services/OwnerRowUniqueness.test.ts +3 -0
  282. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +0 -1
  283. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +56 -6
  284. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -1
  285. package/Tests/Server/Services/SsoRequirementReads.test.ts +454 -0
  286. package/Tests/Server/Services/SsoRequirementWrites.test.ts +529 -0
  287. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
  288. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +107 -89
  289. package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +1068 -176
  290. package/Tests/Server/Services/TeamComplianceSettingService.test.ts +1962 -200
  291. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +654 -297
  292. package/Tests/Server/Types/Database/Permissions/RetentionOverrideColumns.test.ts +784 -0
  293. package/Tests/Server/Types/Database/Permissions/SsoScalePlanGate.test.ts +418 -0
  294. package/Tests/Server/Utils/AI/AIAlertGating.test.ts +0 -1
  295. package/Tests/Server/Utils/AI/AIInvestigationEngineRunLimits.test.ts +136 -0
  296. package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +15 -14
  297. package/Tests/Server/Utils/AI/AgentContextCompactor.test.ts +351 -0
  298. package/Tests/Server/Utils/AI/ChatAgentRunnerSharedThread.test.ts +842 -0
  299. package/Tests/Server/Utils/AI/ChatRunCancellation.test.ts +195 -0
  300. package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +10 -57
  301. package/Tests/Server/Utils/AI/FixRunBudget.test.ts +20 -24
  302. package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +7 -30
  303. package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +225 -29
  304. package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +266 -25
  305. package/Tests/Server/Utils/AI/InvestigationThread.test.ts +580 -0
  306. package/Tests/Server/Utils/AI/InvestigationThreadService.test.ts +801 -0
  307. package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +525 -43
  308. package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +4 -2
  309. package/Tests/Server/Utils/AI/LLMServiceUnreachableProvider.test.ts +435 -0
  310. package/Tests/Server/Utils/AI/ObservabilityAssistantLimits.test.ts +462 -0
  311. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +14 -25
  312. package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +2 -0
  313. package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +297 -15
  314. package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +10 -6
  315. package/Tests/Server/Utils/AI/ToolOutputPager.test.ts +382 -0
  316. package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +23 -4
  317. package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +25 -6
  318. package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +14 -3
  319. package/Tests/Server/Utils/EditionEnforcement.test.ts +107 -147
  320. package/Tests/Server/Utils/{CommunityEditionSsoReport.test.ts → RelaxedScimTeamLocksReport.test.ts} +212 -208
  321. package/Tests/Server/Utils/SameOriginRequest.test.ts +372 -0
  322. package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +20 -0
  323. package/Tests/Server/Utils/Telemetry/MessageQueueDiscovery.test.ts +2590 -0
  324. package/Tests/Server/Utils/Telemetry/MessageQueueSpanQueryTwin.ts +246 -0
  325. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +23 -0
  326. package/Tests/Types/AI/AIAgentRunLimits.test.ts +255 -0
  327. package/Tests/Types/Code/JsonSyntax.test.ts +1300 -0
  328. package/Tests/Types/CustomField/CustomFieldCreateSettings.test.ts +1113 -0
  329. package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +91 -0
  330. package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +30 -0
  331. package/Tests/Types/Incident/IncidentFormIpAllowlist.test.ts +227 -0
  332. package/Tests/Types/Incident/IncidentFormPublic.test.ts +1916 -0
  333. package/Tests/Types/MessageQueue/MessageQueueEntityKey.test.ts +916 -0
  334. package/Tests/Types/MessageQueue/MessageQueueIdentity.test.ts +567 -0
  335. package/Tests/Types/MessageQueue/MessageQueueManualIdentity.test.ts +686 -0
  336. package/Tests/Types/MessageQueue/MessageQueueMetricCatalog.test.ts +1726 -0
  337. package/Tests/Types/MessageQueue/MessageQueueMetricResolution.test.ts +1758 -0
  338. package/Tests/Types/MessageQueue/MessagingInstrumentationFixtures.test.ts +4686 -0
  339. package/Tests/Types/MessageQueue/MessagingSystem.test.ts +840 -0
  340. package/Tests/Types/MessageQueue/MessagingTelemetryFixtures.ts +3287 -0
  341. package/Tests/Types/MessageQueue/MessagingTelemetryResolver.test.ts +2966 -0
  342. package/Tests/Types/Monitor/MessageQueueAlertTemplates.test.ts +5401 -0
  343. package/Tests/Types/Monitor/MetricEngineFold.ts +154 -0
  344. package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +5 -3
  345. package/Tests/Types/Team/ComplianceRule.test.ts +588 -37
  346. package/Tests/Types/Team/TeamComplianceStatus.test.ts +64 -11
  347. package/Tests/Types/XML.test.ts +51 -0
  348. package/Tests/UI/Components/CodeEditor/CodeEditor.test.tsx +2362 -0
  349. package/Tests/UI/Components/CodeEditor/CodeEditorCommands.test.ts +810 -0
  350. package/Tests/UI/Components/CodeEditor/CodeEditorHighlight.test.ts +338 -0
  351. package/Tests/UI/Components/CodeEditor/CodeEditorLanguages.test.ts +222 -0
  352. package/Tests/UI/Components/CodeEditor/CodeEditorStyles.test.ts +807 -0
  353. package/Tests/UI/Components/CodeEditor/NoMonaco.test.ts +245 -0
  354. package/Tests/UI/Components/CodeEditor/YamlEditor.test.tsx +729 -0
  355. package/Tests/UI/Components/CopyTextButton.test.tsx +76 -0
  356. package/Tests/UI/Components/EditionLabelLapseCopy.ts +51 -14
  357. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +131 -23
  358. package/Tests/UI/Components/ErrorMessageAction.test.tsx +142 -0
  359. package/Tests/UI/Components/FacetSidebarInScope.test.tsx +459 -0
  360. package/Tests/UI/Components/FacetValuesInScope.test.ts +270 -0
  361. package/Tests/UI/Components/Forms/FormFieldCodeEditors.test.tsx +294 -0
  362. package/Tests/UI/Components/Forms/FormFieldMarkdown.test.tsx +126 -0
  363. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +22 -75
  364. package/Tests/UI/Components/Forms/ModelFormOnBeforeCreateMiscData.test.tsx +254 -0
  365. package/Tests/UI/Components/Icon.test.tsx +32 -0
  366. package/Tests/UI/Components/Input.test.tsx +31 -0
  367. package/Tests/UI/Components/LockedFilterChipScope.test.tsx +501 -0
  368. package/Tests/UI/Components/MarkdownConverters.test.ts +253 -1
  369. package/Tests/UI/Components/MarkdownEditor.test.tsx +2785 -2
  370. package/Tests/UI/Components/MarkdownEditorHistory.test.ts +243 -0
  371. package/Tests/UI/Components/MarkdownListEditing.test.ts +1118 -0
  372. package/Tests/UI/Components/MarkdownPaste.test.ts +1180 -0
  373. package/Tests/UI/Components/MarkdownViewerCopy.test.tsx +466 -0
  374. package/Tests/UI/Components/MarkdownVisualEditing.test.ts +1089 -0
  375. package/Tests/UI/Components/ModelTable/BaseModelTableEmptyStateAction.test.tsx +623 -0
  376. package/Tests/UI/Components/ResetObjectID.test.tsx +282 -0
  377. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  378. package/Tests/UI/Components/Table/EmptyTableMessage.test.ts +439 -0
  379. package/Tests/UI/Components/Table/TableEmptyState.test.tsx +352 -0
  380. package/Tests/UI/Components/TableRowMobileTitles.test.tsx +78 -0
  381. package/Tests/UI/Components/TextArea.test.tsx +19 -0
  382. package/Tests/UI/Components/Workflow/ModelColumnEditor.render.test.tsx +12 -29
  383. package/Tests/UI/Components/fixtures/MarkdownPasteFixtures.ts +460 -0
  384. package/Tests/UI/EsbuildConfig.test.ts +115 -39
  385. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +4 -4
  386. package/Tests/UI/Monitor/MonitorLogSummaryRender.test.tsx +377 -0
  387. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +81 -1
  388. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +17 -0
  389. package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
  390. package/Tests/Utils/Markdown/DashboardMarkdownRenderer.ts +81 -0
  391. package/Tests/Utils/Markdown/UntrustedMarkdown.test.ts +1339 -0
  392. package/Tests/Utils/Monitor/MonitorLogSummaryUtil.test.ts +862 -0
  393. package/Types/AI/AIAgentRunLimits.ts +146 -0
  394. package/Types/Code/CodeType.ts +2 -0
  395. package/Types/Code/JsonSyntax.ts +923 -0
  396. package/Types/CustomField/CustomFieldCreateSettings.ts +549 -0
  397. package/Types/CustomField/CustomFieldMappingCatalog.ts +77 -0
  398. package/Types/CustomField/CustomFieldValueValidator.ts +10 -7
  399. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +1 -1
  400. package/Types/Icon/IconProp.ts +2 -0
  401. package/Types/Incident/IncidentFormIpAllowlist.ts +206 -0
  402. package/Types/Incident/IncidentFormPublic.ts +1145 -0
  403. package/Types/Kubernetes/KubernetesClusterAiAccess.ts +10 -3
  404. package/Types/MessageQueue/MessageQueueIdentity.ts +256 -0
  405. package/Types/MessageQueue/MessageQueueManualIdentity.ts +325 -0
  406. package/Types/MessageQueue/MessageQueueMetricCatalog.ts +1357 -0
  407. package/Types/MessageQueue/MessagingSystem.ts +518 -0
  408. package/Types/MessageQueue/MessagingTelemetryResolver.ts +2311 -0
  409. package/Types/Monitor/MessageQueueAlertTemplates.ts +2128 -0
  410. package/Types/Permission.ts +310 -0
  411. package/Types/ResourceAiAgent/ResourceAiAccess.ts +10 -4
  412. package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
  413. package/Types/Rules/RuleRun.ts +4 -0
  414. package/Types/Team/ComplianceNotificationChannel.ts +4 -3
  415. package/Types/Team/ComplianceRule.ts +71 -18
  416. package/Types/Team/ComplianceRuleType.ts +2 -2
  417. package/Types/Team/TeamComplianceStatus.ts +6 -2
  418. package/Types/Telemetry/EntityType.ts +16 -0
  419. package/Types/Telemetry/LockedFilterDetail.ts +22 -0
  420. package/Types/XML.ts +26 -0
  421. package/UI/Components/CodeEditor/CodeEditor.css +379 -0
  422. package/UI/Components/CodeEditor/CodeEditor.tsx +1128 -294
  423. package/UI/Components/CodeEditor/CodeEditorCommands.ts +774 -0
  424. package/UI/Components/CodeEditor/CodeEditorHighlight.ts +106 -0
  425. package/UI/Components/CodeEditor/CodeEditorLanguages.ts +164 -0
  426. package/UI/Components/CodeEditor/YamlEditor.tsx +28 -326
  427. package/UI/Components/CopyTextButton/CopyTextButton.tsx +5 -1
  428. package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +6 -25
  429. package/UI/Components/EditionLabel/EditionLabel.tsx +14 -13
  430. package/UI/Components/ErrorMessage/ErrorMessage.tsx +11 -1
  431. package/UI/Components/Forms/Fields/FormField.tsx +8 -0
  432. package/UI/Components/Forms/Types/Field.ts +8 -0
  433. package/UI/Components/Icon/Icon.tsx +18 -0
  434. package/UI/Components/Input/Input.tsx +11 -4
  435. package/UI/Components/LogsViewer/LogsViewer.tsx +4 -0
  436. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +21 -3
  437. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  438. package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +877 -79
  439. package/UI/Components/Markdown.tsx/MarkdownEditorHistory.ts +284 -0
  440. package/UI/Components/Markdown.tsx/MarkdownListEditing.ts +1362 -0
  441. package/UI/Components/Markdown.tsx/MarkdownPaste.ts +1326 -0
  442. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +106 -10
  443. package/UI/Components/Markdown.tsx/MarkdownVisualEditing.ts +1032 -0
  444. package/UI/Components/ModelTable/BaseModelTable.tsx +85 -7
  445. package/UI/Components/ResetObjectID/ResetObjectID.tsx +35 -9
  446. package/UI/Components/Table/EmptyTableMessage.ts +81 -0
  447. package/UI/Components/Table/Table.tsx +50 -21
  448. package/UI/Components/Table/TableRow.tsx +9 -1
  449. package/UI/Components/TelemetryViewer/FacetVisibility.ts +97 -2
  450. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +13 -0
  451. package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +214 -7
  452. package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +21 -3
  453. package/UI/Components/TextArea/TextArea.tsx +9 -2
  454. package/UI/Components/Workflow/ModelFieldPicker.tsx +10 -12
  455. package/UI/Styles/Theme.css +8 -0
  456. package/UI/esbuild-config.js +2 -32
  457. package/Utils/LabelRuleImportExport.ts +2 -0
  458. package/Utils/Markdown/UntrustedMarkdown.ts +1513 -0
  459. package/Utils/Monitor/IncomingEmailMonitorRequestUtil.ts +41 -0
  460. package/Utils/Monitor/MonitorLogSummaryUtil.ts +212 -0
  461. package/Utils/Telemetry/EntityKey.ts +48 -0
  462. package/build/dist/Models/DatabaseModels/AIConversation.js +125 -1
  463. package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
  464. package/build/dist/Models/DatabaseModels/CephCluster.js +12 -0
  465. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
  466. package/build/dist/Models/DatabaseModels/CloudResource.js +12 -0
  467. package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
  468. package/build/dist/Models/DatabaseModels/DatabaseServer.js +12 -0
  469. package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
  470. package/build/dist/Models/DatabaseModels/DockerHost.js +12 -0
  471. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  472. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +12 -0
  473. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
  474. package/build/dist/Models/DatabaseModels/GlobalOidc.js +0 -4
  475. package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
  476. package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +0 -4
  477. package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
  478. package/build/dist/Models/DatabaseModels/GlobalSso.js +0 -4
  479. package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
  480. package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +0 -4
  481. package/build/dist/Models/DatabaseModels/GlobalSsoProject.js.map +1 -1
  482. package/build/dist/Models/DatabaseModels/Host.js +12 -0
  483. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  484. package/build/dist/Models/DatabaseModels/IncidentForm.js +605 -0
  485. package/build/dist/Models/DatabaseModels/IncidentForm.js.map +1 -0
  486. package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js +299 -0
  487. package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js.map +1 -0
  488. package/build/dist/Models/DatabaseModels/IncidentTemplate.js +60 -0
  489. package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
  490. package/build/dist/Models/DatabaseModels/Index.js +14 -0
  491. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  492. package/build/dist/Models/DatabaseModels/IoTFleet.js +12 -0
  493. package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
  494. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +12 -0
  495. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  496. package/build/dist/Models/DatabaseModels/MessageQueue.js +1106 -0
  497. package/build/dist/Models/DatabaseModels/MessageQueue.js.map +1 -0
  498. package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js +562 -0
  499. package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js.map +1 -0
  500. package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js +643 -0
  501. package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js.map +1 -0
  502. package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js +506 -0
  503. package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js.map +1 -0
  504. package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js +505 -0
  505. package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js.map +1 -0
  506. package/build/dist/Models/DatabaseModels/PodmanHost.js +12 -0
  507. package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
  508. package/build/dist/Models/DatabaseModels/Project.js +61 -0
  509. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  510. package/build/dist/Models/DatabaseModels/ProjectOidc.js +0 -4
  511. package/build/dist/Models/DatabaseModels/ProjectOidc.js.map +1 -1
  512. package/build/dist/Models/DatabaseModels/ProjectSso.js +0 -4
  513. package/build/dist/Models/DatabaseModels/ProjectSso.js.map +1 -1
  514. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +12 -0
  515. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
  516. package/build/dist/Models/DatabaseModels/RumApplication.js +12 -0
  517. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  518. package/build/dist/Models/DatabaseModels/ServerlessFunction.js +12 -0
  519. package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -1
  520. package/build/dist/Models/DatabaseModels/Service.js +12 -0
  521. package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
  522. package/build/dist/Models/DatabaseModels/StatusPageOidc.js +0 -4
  523. package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
  524. package/build/dist/Models/DatabaseModels/StatusPageSso.js +0 -4
  525. package/build/dist/Models/DatabaseModels/StatusPageSso.js.map +1 -1
  526. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +49 -3
  527. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
  528. package/build/dist/Models/DatabaseModels/VMwareVCenter.js +12 -0
  529. package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
  530. package/build/dist/Server/API/AIChatAPI.js +9 -103
  531. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  532. package/build/dist/Server/API/AIInvestigationAPI.js +3 -3
  533. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  534. package/build/dist/Server/API/AIInvestigationConversationAPI.js +162 -0
  535. package/build/dist/Server/API/AIInvestigationConversationAPI.js.map +1 -0
  536. package/build/dist/Server/API/IncidentFormAPI.js +245 -0
  537. package/build/dist/Server/API/IncidentFormAPI.js.map +1 -0
  538. package/build/dist/Server/API/ProjectOIDC.js +16 -24
  539. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  540. package/build/dist/Server/API/ProjectSSO.js +16 -24
  541. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  542. package/build/dist/Server/API/StatusPageAPI.js +42 -75
  543. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  544. package/build/dist/Server/Enterprise/EnterpriseEdition.js +79 -25
  545. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -1
  546. package/build/dist/Server/Enterprise/EnterpriseFeature.js +24 -3
  547. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -1
  548. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +1 -1
  549. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -1
  550. package/build/dist/Server/EnvironmentConfig.js +1 -1
  551. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js +63 -0
  552. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js.map +1 -0
  553. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js +41 -0
  554. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js.map +1 -0
  555. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js +40 -0
  556. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js.map +1 -0
  557. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js +183 -0
  558. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js.map +1 -0
  559. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  560. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  561. package/build/dist/Server/Middleware/IncidentFormRateLimit.js +559 -0
  562. package/build/dist/Server/Middleware/IncidentFormRateLimit.js.map +1 -0
  563. package/build/dist/Server/Middleware/UserAuthorization.js +11 -30
  564. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  565. package/build/dist/Server/Services/AIService.js +10 -13
  566. package/build/dist/Server/Services/AIService.js.map +1 -1
  567. package/build/dist/Server/Services/IncidentCustomFieldService.js +83 -0
  568. package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
  569. package/build/dist/Server/Services/IncidentEpisodeMemberService.js +8 -4
  570. package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
  571. package/build/dist/Server/Services/IncidentEpisodeService.js +10 -1
  572. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  573. package/build/dist/Server/Services/IncidentFormService.js +1202 -0
  574. package/build/dist/Server/Services/IncidentFormService.js.map +1 -0
  575. package/build/dist/Server/Services/IncidentFormSubmissionService.js +91 -0
  576. package/build/dist/Server/Services/IncidentFormSubmissionService.js.map +1 -0
  577. package/build/dist/Server/Services/IncidentGroupingEngineService.js +20 -8
  578. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  579. package/build/dist/Server/Services/IncidentService.js +106 -4
  580. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  581. package/build/dist/Server/Services/IncidentTemplateService.js +18 -0
  582. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  583. package/build/dist/Server/Services/Index.js +14 -0
  584. package/build/dist/Server/Services/Index.js.map +1 -1
  585. package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js +262 -0
  586. package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js.map +1 -0
  587. package/build/dist/Server/Services/MessageQueueLabelRuleService.js +13 -0
  588. package/build/dist/Server/Services/MessageQueueLabelRuleService.js.map +1 -0
  589. package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js +334 -0
  590. package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js.map +1 -0
  591. package/build/dist/Server/Services/MessageQueueOwnerRuleService.js +13 -0
  592. package/build/dist/Server/Services/MessageQueueOwnerRuleService.js.map +1 -0
  593. package/build/dist/Server/Services/MessageQueueOwnerTeamService.js +62 -0
  594. package/build/dist/Server/Services/MessageQueueOwnerTeamService.js.map +1 -0
  595. package/build/dist/Server/Services/MessageQueueOwnerUserService.js +62 -0
  596. package/build/dist/Server/Services/MessageQueueOwnerUserService.js.map +1 -0
  597. package/build/dist/Server/Services/MessageQueueService.js +1140 -0
  598. package/build/dist/Server/Services/MessageQueueService.js.map +1 -0
  599. package/build/dist/Server/Services/OpenTelemetryIngestService.js +25 -4
  600. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  601. package/build/dist/Server/Services/ProjectService.js +0 -54
  602. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  603. package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -4
  604. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  605. package/build/dist/Server/Services/StatusPageService.js +0 -46
  606. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  607. package/build/dist/Server/Services/TeamComplianceSettingService.js +120 -31
  608. package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
  609. package/build/dist/Server/Services/UserNotificationRuleService.js +8 -1
  610. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  611. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +12 -3
  612. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
  613. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +6 -3
  614. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  615. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +109 -37
  616. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  617. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +16 -0
  618. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  619. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +3 -3
  620. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +9 -6
  621. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  622. package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js +128 -0
  623. package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js.map +1 -0
  624. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +192 -50
  625. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
  626. package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js +133 -0
  627. package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js.map +1 -0
  628. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +53 -13
  629. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  630. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
  631. package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js +206 -0
  632. package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js.map +1 -0
  633. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +53 -26
  634. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
  635. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +4 -2
  636. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
  637. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +1 -29
  638. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
  639. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +24 -24
  640. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
  641. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +7 -2
  642. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  643. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +29 -14
  644. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  645. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +38 -14
  646. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -1
  647. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +2 -0
  648. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -1
  649. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +40 -10
  650. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  651. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +19 -7
  652. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  653. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +19 -7
  654. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  655. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +15 -18
  656. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
  657. package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js +412 -0
  658. package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js.map +1 -0
  659. package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js +495 -0
  660. package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js.map +1 -0
  661. package/build/dist/Server/Utils/AI/Toolbox/Serializer.js +10 -3
  662. package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -1
  663. package/build/dist/Server/Utils/EditionEnforcement.js +20 -158
  664. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -1
  665. package/build/dist/Server/Utils/LLM/LLMService.js +193 -54
  666. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  667. package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js +160 -0
  668. package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js.map +1 -0
  669. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
  670. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  671. package/build/dist/Server/Utils/SameOriginRequest.js +151 -0
  672. package/build/dist/Server/Utils/SameOriginRequest.js.map +1 -0
  673. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
  674. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
  675. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -1
  676. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  677. package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js +1015 -0
  678. package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js.map +1 -0
  679. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +4 -1
  680. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
  681. package/build/dist/Server/Utils/VendorAssets.js +3 -3
  682. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +3 -1
  683. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  684. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +3 -1
  685. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
  686. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +10 -1
  687. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  688. package/build/dist/Types/AI/AIAgentRunLimits.js +91 -0
  689. package/build/dist/Types/AI/AIAgentRunLimits.js.map +1 -0
  690. package/build/dist/Types/Code/CodeType.js +2 -0
  691. package/build/dist/Types/Code/CodeType.js.map +1 -1
  692. package/build/dist/Types/Code/JsonSyntax.js +604 -0
  693. package/build/dist/Types/Code/JsonSyntax.js.map +1 -0
  694. package/build/dist/Types/CustomField/CustomFieldCreateSettings.js +310 -0
  695. package/build/dist/Types/CustomField/CustomFieldCreateSettings.js.map +1 -0
  696. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +38 -0
  697. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -1
  698. package/build/dist/Types/CustomField/CustomFieldValueValidator.js +10 -7
  699. package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -1
  700. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +1 -1
  701. package/build/dist/Types/Icon/IconProp.js +2 -0
  702. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  703. package/build/dist/Types/Incident/IncidentFormIpAllowlist.js +119 -0
  704. package/build/dist/Types/Incident/IncidentFormIpAllowlist.js.map +1 -0
  705. package/build/dist/Types/Incident/IncidentFormPublic.js +678 -0
  706. package/build/dist/Types/Incident/IncidentFormPublic.js.map +1 -0
  707. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +10 -3
  708. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
  709. package/build/dist/Types/MessageQueue/MessageQueueIdentity.js +184 -0
  710. package/build/dist/Types/MessageQueue/MessageQueueIdentity.js.map +1 -0
  711. package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js +190 -0
  712. package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js.map +1 -0
  713. package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js +1057 -0
  714. package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js.map +1 -0
  715. package/build/dist/Types/MessageQueue/MessagingSystem.js +394 -0
  716. package/build/dist/Types/MessageQueue/MessagingSystem.js.map +1 -0
  717. package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js +1768 -0
  718. package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js.map +1 -0
  719. package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js +1207 -0
  720. package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js.map +1 -0
  721. package/build/dist/Types/Permission.js +274 -0
  722. package/build/dist/Types/Permission.js.map +1 -1
  723. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +10 -4
  724. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -1
  725. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +12 -0
  726. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  727. package/build/dist/Types/Rules/RuleRun.js +4 -0
  728. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  729. package/build/dist/Types/Team/ComplianceNotificationChannel.js +4 -3
  730. package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -1
  731. package/build/dist/Types/Team/ComplianceRule.js +48 -14
  732. package/build/dist/Types/Team/ComplianceRule.js.map +1 -1
  733. package/build/dist/Types/Team/ComplianceRuleType.js +2 -2
  734. package/build/dist/Types/Telemetry/EntityType.js +16 -0
  735. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  736. package/build/dist/Types/XML.js +23 -0
  737. package/build/dist/Types/XML.js.map +1 -1
  738. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +641 -266
  739. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  740. package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js +464 -0
  741. package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js.map +1 -0
  742. package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js +69 -0
  743. package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js.map +1 -0
  744. package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js +108 -0
  745. package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js.map +1 -0
  746. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +14 -186
  747. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -1
  748. package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
  749. package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
  750. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +5 -14
  751. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -1
  752. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +14 -13
  753. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  754. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +1 -1
  755. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
  756. package/build/dist/UI/Components/Forms/Fields/FormField.js +8 -3
  757. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  758. package/build/dist/UI/Components/Icon/Icon.js +8 -0
  759. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  760. package/build/dist/UI/Components/Input/Input.js +11 -3
  761. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  762. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +2 -1
  763. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  764. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +14 -4
  765. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  766. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  767. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  768. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +710 -65
  769. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
  770. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js +238 -0
  771. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js.map +1 -0
  772. package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js +1028 -0
  773. package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js.map +1 -0
  774. package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js +1088 -0
  775. package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js.map +1 -0
  776. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +70 -10
  777. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  778. package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js +887 -0
  779. package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js.map +1 -0
  780. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +57 -6
  781. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  782. package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js +7 -5
  783. package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js.map +1 -1
  784. package/build/dist/UI/Components/Table/EmptyTableMessage.js +51 -0
  785. package/build/dist/UI/Components/Table/EmptyTableMessage.js.map +1 -0
  786. package/build/dist/UI/Components/Table/Table.js +30 -11
  787. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  788. package/build/dist/UI/Components/Table/TableRow.js +9 -2
  789. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  790. package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +63 -1
  791. package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -1
  792. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +4 -2
  793. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  794. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +91 -10
  795. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
  796. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +14 -4
  797. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
  798. package/build/dist/UI/Components/TextArea/TextArea.js +9 -3
  799. package/build/dist/UI/Components/TextArea/TextArea.js.map +1 -1
  800. package/build/dist/UI/Components/Workflow/ModelFieldPicker.js +1 -2
  801. package/build/dist/UI/Components/Workflow/ModelFieldPicker.js.map +1 -1
  802. package/build/dist/Utils/LabelRuleImportExport.js +2 -0
  803. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  804. package/build/dist/Utils/Markdown/UntrustedMarkdown.js +988 -0
  805. package/build/dist/Utils/Markdown/UntrustedMarkdown.js.map +1 -0
  806. package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js +34 -0
  807. package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js.map +1 -0
  808. package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js +148 -0
  809. package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js.map +1 -0
  810. package/build/dist/Utils/Telemetry/EntityKey.js +36 -0
  811. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  812. package/package.json +1 -3
  813. package/Server/Utils/CommunityEditionSsoReport.ts +0 -361
  814. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +0 -616
  815. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +0 -217
  816. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +0 -271
  817. package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +0 -215
  818. package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +0 -784
  819. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +0 -518
  820. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +0 -419
  821. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +0 -769
  822. package/Tests/UI/Components/CodeEditor.test.tsx +0 -638
  823. package/Tests/UI/Components/MonacoLoader.test.ts +0 -67
  824. package/Tests/UI/Components/MonacoRuntime.test.ts +0 -121
  825. package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +0 -329
  826. package/Tests/UI/Components/YamlEditor.test.tsx +0 -847
  827. package/UI/Components/CodeEditor/MonacoLoader.ts +0 -36
  828. package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +0 -319
  829. package/UI/Components/Telemetry/TelemetryRetentionConfigSummary.tsx +0 -223
  830. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +0 -223
  831. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +0 -1
  832. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +0 -34
  833. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +0 -1
  834. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +0 -171
  835. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +0 -1
  836. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js +0 -119
  837. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js.map +0 -1
@@ -0,0 +1,1326 @@
1
+ /*
2
+ * Clipboard -> markdown for the MarkdownEditor's paste handlers.
3
+ *
4
+ * Markdown is the editor's source of truth, so a paste is turned into
5
+ * markdown first and only then rendered into the visual editor (or inserted
6
+ * into the source textarea). What is on the clipboard decides how:
7
+ *
8
+ * - text/html -- from Word, Outlook, Google Docs, a web page, or a note
9
+ * rendered by OneUptime itself -- is cleaned up as a DOM tree: lists are
10
+ * rebuilt with their nesting, bold / italic / strikethrough are read off
11
+ * inline styles, links and images are kept only for safe schemes, and
12
+ * whatever is not content (styles, buttons, icons) is dropped. The editor's
13
+ * own serializer then writes it out, so the result is markdown the editor
14
+ * already round-trips;
15
+ * - plain text is taken as markdown, as it always was, once the bullet
16
+ * characters other apps write ("•", "◦", Word's "o" and "§" before a
17
+ * tab) have become markdown list items at the right depth.
18
+ *
19
+ * Clipboard HTML is never assigned to innerHTML: Chromium runs an <img>'s
20
+ * onerror handler for markup parsed into a detached element. It is parsed
21
+ * with DOMParser, whose document is inert -- nothing in it loads or runs --
22
+ * and nothing from it reaches the page except the markdown written here.
23
+ */
24
+
25
+ import { domToMarkdown } from "./MarkdownConverters";
26
+ import {
27
+ TAB_ONLY_BULLET_GLYPHS,
28
+ TEXT_BULLET_GLYPHS,
29
+ } from "./MarkdownListEditing";
30
+
31
+ // What the paste handlers read from a ClipboardEvent's DataTransfer.
32
+ export interface PastedClipboard {
33
+ getData: (format: string) => string;
34
+ types?: ReadonlyArray<string> | undefined;
35
+ }
36
+
37
+ export interface ClipboardToMarkdownOptions {
38
+ /*
39
+ * Whether the caller has image files from this paste that it can upload.
40
+ * Defaults to whether the clipboard lists any files at all.
41
+ */
42
+ hasImageFiles?: boolean | undefined;
43
+ }
44
+
45
+ /*
46
+ * ---------------------------------------------------------------------------
47
+ * Plain text
48
+ * ---------------------------------------------------------------------------
49
+ */
50
+
51
+ const RE_GLYPH_BULLET_LINE: RegExp = new RegExp(
52
+ `^([ \\t]*)(?:([${TEXT_BULLET_GLYPHS}])|([${TAB_ONLY_BULLET_GLYPHS}])(?=\\t))[ \\t\\u00a0]+(.*)$`,
53
+ );
54
+ const RE_PAREN_NUMBER_LINE: RegExp = /^([ \t]*)(\d{1,9})\)[ \t]+(.*)$/;
55
+ const RE_TEXT_FENCE: RegExp = /^[ \t]*(`{3,}|~{3,})/;
56
+ const RE_LINE_BREAKS: RegExp = /\r\n?/g;
57
+
58
+ // A tab advances to the next multiple of four columns, as in CommonMark.
59
+ const TAB_WIDTH: number = 4;
60
+
61
+ const indentColumns: (whitespace: string) => number = (
62
+ whitespace: string,
63
+ ): number => {
64
+ let column: number = 0;
65
+ for (const ch of whitespace) {
66
+ column += ch === "\t" ? TAB_WIDTH - (column % TAB_WIDTH) : 1;
67
+ }
68
+ return column;
69
+ };
70
+
71
+ /*
72
+ * Word writes a nested bullet's level only through its character -- "•",
73
+ * then "o", then "§" -- with no indentation in its plain text. These are
74
+ * the depths those characters (and the second and third level bullets of
75
+ * Slack and Google Docs) stand for when no indentation says otherwise.
76
+ */
77
+ const GLYPH_DEPTH: { [glyph: string]: number } = {
78
+ o: 1,
79
+ "◦": 1,
80
+ "○": 1,
81
+ "§": 2,
82
+ "\uF0A7": 2,
83
+ "▪": 2,
84
+ "■": 2,
85
+ };
86
+
87
+ interface BulletLine {
88
+ index: number;
89
+ indent: number;
90
+ glyph: string;
91
+ text: string;
92
+ }
93
+
94
+ /*
95
+ * Turns the bullet characters other apps put in their plain text into
96
+ * markdown list items, nested by their indentation -- or, for Word, which
97
+ * does not indent its plain text, by which of its bullet characters a line
98
+ * uses. "1) step" becomes "1. step", the only ordered form the editor's
99
+ * parser reads. Lines inside a fenced code block are left alone, and so is
100
+ * text with no such line at all, so prose like "price • quality" or an
101
+ * ordinary markdown document comes back exactly as it went in.
102
+ */
103
+ export const normalizePlainTextListMarkers: (text: string) => string = (
104
+ text: string,
105
+ ): string => {
106
+ const lines: Array<string> = text.replace(RE_LINE_BREAKS, "\n").split("\n");
107
+ const bullets: Array<BulletLine> = [];
108
+ let found: boolean = false;
109
+ let fence: string | null = null;
110
+
111
+ for (let index: number = 0; index < lines.length; index++) {
112
+ const line: string = lines[index] || "";
113
+ const fenceMatch: RegExpMatchArray | null = line.match(RE_TEXT_FENCE);
114
+ if (fence !== null) {
115
+ if (fenceMatch && (fenceMatch[1] || "").charAt(0) === fence.charAt(0)) {
116
+ fence = null;
117
+ }
118
+ continue;
119
+ }
120
+ if (fenceMatch) {
121
+ fence = fenceMatch[1] || "```";
122
+ continue;
123
+ }
124
+ const bullet: RegExpMatchArray | null = line.match(RE_GLYPH_BULLET_LINE);
125
+ if (bullet) {
126
+ found = true;
127
+ bullets.push({
128
+ index,
129
+ indent: indentColumns(bullet[1] || ""),
130
+ glyph: bullet[2] || bullet[3] || "",
131
+ text: bullet[4] || "",
132
+ });
133
+ continue;
134
+ }
135
+ const numbered: RegExpMatchArray | null = line.match(RE_PAREN_NUMBER_LINE);
136
+ if (numbered) {
137
+ found = true;
138
+ lines[index] =
139
+ `${numbered[1] || ""}${numbered[2] || ""}. ${numbered[3] || ""}`;
140
+ }
141
+ }
142
+
143
+ if (!found) {
144
+ return text;
145
+ }
146
+
147
+ const indented: boolean = bullets.some((bullet: BulletLine): boolean => {
148
+ return bullet.indent > 0;
149
+ });
150
+
151
+ /*
152
+ * Depth by indentation: each distinct indent deeper than the one above
153
+ * opens a level, and a shallower one closes levels back down to it. A
154
+ * paragraph between two bullets ends the list, so the next bullet starts
155
+ * again at the top.
156
+ */
157
+ const open: Array<number> = [];
158
+ let depth: number = 0;
159
+ let previousIndex: number = -2;
160
+ for (const bullet of bullets) {
161
+ const gap: Array<string> = lines.slice(previousIndex + 1, bullet.index);
162
+ const listInterrupted: boolean =
163
+ previousIndex < 0 ||
164
+ gap.some((line: string): boolean => {
165
+ return line.trim().length > 0;
166
+ });
167
+ if (listInterrupted) {
168
+ open.length = 0;
169
+ depth = 0;
170
+ }
171
+
172
+ if (indented) {
173
+ while (
174
+ open.length > 0 &&
175
+ (open[open.length - 1] as number) > bullet.indent
176
+ ) {
177
+ open.pop();
178
+ }
179
+ if (
180
+ open.length === 0 ||
181
+ (open[open.length - 1] as number) < bullet.indent
182
+ ) {
183
+ open.push(bullet.indent);
184
+ }
185
+ depth = open.length - 1;
186
+ } else {
187
+ const wanted: number = GLYPH_DEPTH[bullet.glyph] ?? 0;
188
+ // A level can only open one deeper than the item above it.
189
+ depth = listInterrupted ? 0 : Math.min(wanted, depth + 1);
190
+ }
191
+
192
+ lines[bullet.index] = `${" ".repeat(depth)}- ${bullet.text}`;
193
+ previousIndex = bullet.index;
194
+ }
195
+
196
+ return lines.join("\n");
197
+ };
198
+
199
+ /*
200
+ * ---------------------------------------------------------------------------
201
+ * HTML
202
+ * ---------------------------------------------------------------------------
203
+ */
204
+
205
+ // Never content: dropped with everything inside them.
206
+ const NON_CONTENT_SELECTOR: string = [
207
+ "script",
208
+ "style",
209
+ "meta",
210
+ "link",
211
+ "title",
212
+ "template",
213
+ "noscript",
214
+ "iframe",
215
+ "frame",
216
+ "frameset",
217
+ "object",
218
+ "embed",
219
+ "applet",
220
+ "canvas",
221
+ "audio",
222
+ "video",
223
+ "source",
224
+ "track",
225
+ "svg",
226
+ "math",
227
+ "button",
228
+ "select",
229
+ "textarea",
230
+ "datalist",
231
+ "dialog",
232
+ "xml",
233
+ /*
234
+ * MarkdownViewer marks the parts of its output that are chrome rather than
235
+ * the document -- a code block's language label and Copy button.
236
+ */
237
+ "[data-markdown-ignore]",
238
+ ].join(", ");
239
+
240
+ const BLOCK_TAGS: Set<string> = new Set<string>([
241
+ "address",
242
+ "article",
243
+ "aside",
244
+ "blockquote",
245
+ "body",
246
+ "br",
247
+ "dd",
248
+ "details",
249
+ "div",
250
+ "dl",
251
+ "dt",
252
+ "fieldset",
253
+ "figcaption",
254
+ "figure",
255
+ "footer",
256
+ "form",
257
+ "h1",
258
+ "h2",
259
+ "h3",
260
+ "h4",
261
+ "h5",
262
+ "h6",
263
+ "header",
264
+ "hr",
265
+ "li",
266
+ "main",
267
+ "nav",
268
+ "ol",
269
+ "p",
270
+ "pre",
271
+ "section",
272
+ "summary",
273
+ "table",
274
+ "tbody",
275
+ "td",
276
+ "tfoot",
277
+ "th",
278
+ "thead",
279
+ "tr",
280
+ "ul",
281
+ ]);
282
+
283
+ // Formatting the serializer writes as markdown, and that is noise when empty.
284
+ const INLINE_FORMATTING_SELECTOR: string =
285
+ "strong, b, em, i, s, del, strike, u, sub, sup";
286
+
287
+ /*
288
+ * What makes clipboard HTML worth converting rather than taking the plain
289
+ * text beside it: structure or formatting that the plain text loses.
290
+ */
291
+ const RICH_CONTENT_SELECTOR: string = [
292
+ "ul",
293
+ "ol",
294
+ "li",
295
+ "h1",
296
+ "h2",
297
+ "h3",
298
+ "h4",
299
+ "h5",
300
+ "h6",
301
+ "blockquote",
302
+ "pre",
303
+ "table",
304
+ "hr",
305
+ "img",
306
+ "a[href]",
307
+ "strong",
308
+ "b",
309
+ "em",
310
+ "i",
311
+ "s",
312
+ "del",
313
+ "strike",
314
+ "u",
315
+ "sub",
316
+ "sup",
317
+ "code",
318
+ ].join(", ");
319
+
320
+ const LINK_SCHEMES: Array<string> = ["http", "https", "mailto", "tel"];
321
+ const IMAGE_SCHEMES: Array<string> = ["http", "https"];
322
+
323
+ const RE_URL_SCHEME: RegExp = /^([a-z][a-z0-9+.-]*):/i;
324
+ const RE_WHITESPACE_RUN: RegExp = /[ \t\n\r\f]+/g;
325
+ const RE_NBSP: RegExp = /\u00a0/g;
326
+ // Docusaurus writes a zero-width space as its heading permalink's only text.
327
+ const RE_ZERO_WIDTH: RegExp = /[\u200b-\u200d\u2060\ufeff]/g;
328
+ const RE_NOT_WHITESPACE: RegExp = /\S/;
329
+ const RE_LEADING_SPACE: RegExp = /^\s+/;
330
+ const RE_TRAILING_SPACE: RegExp = /\s+$/;
331
+ const RE_URL_BREAKING: RegExp = /[\s()]/g;
332
+ const RE_SESSION_RETRY: RegExp = /([?&])sessionRetry=[^&#]*(&?)/;
333
+ const RE_WORD_LIST_STYLE: RegExp = /mso-list:\s*l\d+\s+level(\d+)/i;
334
+ const RE_WORD_ORDERED_MARKER: RegExp = /^\(?[0-9a-zA-Z]{1,5}[.)]/;
335
+ const RE_WORD_MARKER_SPAN: RegExp = /mso-list:\s*ignore/i;
336
+ const RE_HIDDEN_STYLE: RegExp = /mso-hide:\s*all/i;
337
+ const RE_LANGUAGE: RegExp = /^[\w-]+$/;
338
+ const RE_VIEWER_TIMESTAMP: RegExp =
339
+ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,6})?Z$/;
340
+ const RE_DOCS_GUID: RegExp = /^docs-internal-guid/;
341
+
342
+ const tagOf: (node: Node | null | undefined) => string = (
343
+ node: Node | null | undefined,
344
+ ): string => {
345
+ if (!node || node.nodeType !== Node.ELEMENT_NODE) {
346
+ return "";
347
+ }
348
+ return (node as Element).localName.toLowerCase();
349
+ };
350
+
351
+ const isBlock: (node: Node | null | undefined) => boolean = (
352
+ node: Node | null | undefined,
353
+ ): boolean => {
354
+ return BLOCK_TAGS.has(tagOf(node));
355
+ };
356
+
357
+ const isList: (node: Node | null | undefined) => boolean = (
358
+ node: Node | null | undefined,
359
+ ): boolean => {
360
+ const tag: string = tagOf(node);
361
+ return tag === "ul" || tag === "ol";
362
+ };
363
+
364
+ // Replaces an element with its children.
365
+ const unwrap: (element: Element) => void = (element: Element): void => {
366
+ const parent: ParentNode | null = element.parentNode;
367
+ if (!parent) {
368
+ return;
369
+ }
370
+ while (element.firstChild) {
371
+ parent.insertBefore(element.firstChild, element);
372
+ }
373
+ element.remove();
374
+ };
375
+
376
+ const elementsOf: (root: ParentNode, selector: string) => Array<HTMLElement> = (
377
+ root: ParentNode,
378
+ selector: string,
379
+ ): Array<HTMLElement> => {
380
+ return Array.from(root.querySelectorAll<HTMLElement>(selector));
381
+ };
382
+
383
+ const commentsOf: (root: Node) => Array<Comment> = (
384
+ root: Node,
385
+ ): Array<Comment> => {
386
+ const comments: Array<Comment> = [];
387
+ const walk: (node: Node) => void = (node: Node): void => {
388
+ for (const child of Array.from(node.childNodes)) {
389
+ if (child.nodeType === Node.COMMENT_NODE) {
390
+ comments.push(child as Comment);
391
+ } else if (child.nodeType === Node.ELEMENT_NODE) {
392
+ walk(child);
393
+ }
394
+ }
395
+ };
396
+ walk(root);
397
+ return comments;
398
+ };
399
+
400
+ const textNodesOf: (root: Node) => Array<Text> = (root: Node): Array<Text> => {
401
+ const texts: Array<Text> = [];
402
+ const walk: (node: Node) => void = (node: Node): void => {
403
+ for (const child of Array.from(node.childNodes)) {
404
+ if (child.nodeType === Node.TEXT_NODE) {
405
+ texts.push(child as Text);
406
+ } else if (child.nodeType === Node.ELEMENT_NODE) {
407
+ walk(child);
408
+ }
409
+ }
410
+ };
411
+ walk(root);
412
+ return texts;
413
+ };
414
+
415
+ const isBoldWeight: (weight: string) => boolean = (weight: string): boolean => {
416
+ if (weight === "bold" || weight === "bolder") {
417
+ return true;
418
+ }
419
+ const numeric: number = parseInt(weight, 10);
420
+ return !isNaN(numeric) && numeric >= 600;
421
+ };
422
+
423
+ const isNormalWeight: (weight: string) => boolean = (
424
+ weight: string,
425
+ ): boolean => {
426
+ if (weight === "normal" || weight === "lighter") {
427
+ return true;
428
+ }
429
+ const numeric: number = parseInt(weight, 10);
430
+ return !isNaN(numeric) && numeric < 600;
431
+ };
432
+
433
+ /*
434
+ * ---- 1. Things that are not content ---------------------------------------
435
+ */
436
+
437
+ const removeNonContent: (body: HTMLElement) => void = (
438
+ body: HTMLElement,
439
+ ): void => {
440
+ for (const element of elementsOf(body, NON_CONTENT_SELECTOR)) {
441
+ element.remove();
442
+ }
443
+ // A task list's checkbox is content; every other form control is not.
444
+ for (const input of elementsOf(body, "input")) {
445
+ if ((input.getAttribute("type") || "").toLowerCase() !== "checkbox") {
446
+ input.remove();
447
+ }
448
+ }
449
+ for (const element of elementsOf(body, "[style]")) {
450
+ const style: string = element.getAttribute("style") || "";
451
+ if (element.style.display === "none" || RE_HIDDEN_STYLE.test(style)) {
452
+ element.remove();
453
+ }
454
+ }
455
+ /*
456
+ * Word ends every paragraph with an <o:p>, empty or holding a &nbsp; for
457
+ * an empty paragraph. Anything else in one is kept as text.
458
+ */
459
+ for (const element of elementsOf(body, "o\\:p")) {
460
+ if (
461
+ RE_NOT_WHITESPACE.test((element.textContent || "").replace(RE_NBSP, ""))
462
+ ) {
463
+ unwrap(element);
464
+ } else {
465
+ element.remove();
466
+ }
467
+ }
468
+ };
469
+
470
+ /*
471
+ * ---- 2. Word's list paragraphs --------------------------------------------
472
+ */
473
+
474
+ /*
475
+ * Word writes a list as one paragraph per item, each with a
476
+ * "mso-list:l0 level2 lfo1" style and its bullet or number as text between
477
+ * <![if !supportLists]> and <![endif]> (which parse as comments), or in a
478
+ * span styled "mso-list:Ignore". Takes that marker out of the element and
479
+ * returns its text.
480
+ */
481
+ const takeWordListMarker: (element: HTMLElement) => string = (
482
+ element: HTMLElement,
483
+ ): string => {
484
+ let marker: string = "";
485
+ for (const comment of commentsOf(element)) {
486
+ if (comment.data.trim() !== "[if !supportLists]" || !comment.parentNode) {
487
+ continue;
488
+ }
489
+ let node: ChildNode | null = comment.nextSibling;
490
+ while (
491
+ node &&
492
+ !(
493
+ node.nodeType === Node.COMMENT_NODE &&
494
+ (node as Comment).data.trim() === "[endif]"
495
+ )
496
+ ) {
497
+ const next: ChildNode | null = node.nextSibling;
498
+ marker += node.textContent || "";
499
+ node.remove();
500
+ node = next;
501
+ }
502
+ if (node) {
503
+ node.remove();
504
+ }
505
+ comment.remove();
506
+ }
507
+ for (const span of elementsOf(element, "span[style]")) {
508
+ if (
509
+ span.isConnected &&
510
+ RE_WORD_MARKER_SPAN.test(span.getAttribute("style") || "")
511
+ ) {
512
+ marker += span.textContent || "";
513
+ span.remove();
514
+ }
515
+ }
516
+ return marker.replace(RE_NBSP, " ").trim();
517
+ };
518
+
519
+ interface NestedListEntry {
520
+ // 0 for a top-level item.
521
+ depth: number;
522
+ ordered: boolean;
523
+ // The nodes that make up the item.
524
+ content: Array<Node>;
525
+ }
526
+
527
+ /*
528
+ * Builds nested <ul>/<ol> elements out of a flat run of items that each know
529
+ * their depth. An item can only be one level deeper than the one before it;
530
+ * a change between ordered and unordered at the same depth starts a new list
531
+ * there, as it would in markdown.
532
+ */
533
+ const buildNestedLists: (
534
+ doc: Document,
535
+ entries: Array<NestedListEntry>,
536
+ ) => DocumentFragment = (
537
+ doc: Document,
538
+ entries: Array<NestedListEntry>,
539
+ ): DocumentFragment => {
540
+ const fragment: DocumentFragment = doc.createDocumentFragment();
541
+ const levels: Array<{ list: HTMLElement; lastItem: HTMLElement | null }> = [];
542
+ for (const entry of entries) {
543
+ const depth: number = Math.min(entry.depth, levels.length);
544
+ while (levels.length > depth + 1) {
545
+ levels.pop();
546
+ }
547
+ const tag: string = entry.ordered ? "ol" : "ul";
548
+ const current:
549
+ | { list: HTMLElement; lastItem: HTMLElement | null }
550
+ | undefined = levels[depth];
551
+ if (!current || tagOf(current.list) !== tag) {
552
+ const list: HTMLElement = doc.createElement(tag);
553
+ const parent:
554
+ | { list: HTMLElement; lastItem: HTMLElement | null }
555
+ | undefined = levels[depth - 1];
556
+ if (depth === 0 || !parent) {
557
+ fragment.appendChild(list);
558
+ } else {
559
+ if (!parent.lastItem) {
560
+ parent.lastItem = doc.createElement("li");
561
+ parent.list.appendChild(parent.lastItem);
562
+ }
563
+ parent.lastItem.appendChild(list);
564
+ }
565
+ levels.length = depth;
566
+ levels.push({ list, lastItem: null });
567
+ }
568
+ const level: { list: HTMLElement; lastItem: HTMLElement | null } = levels[
569
+ depth
570
+ ] as { list: HTMLElement; lastItem: HTMLElement | null };
571
+ const item: HTMLElement = doc.createElement("li");
572
+ for (const node of entry.content) {
573
+ item.appendChild(node);
574
+ }
575
+ level.list.appendChild(item);
576
+ level.lastItem = item;
577
+ }
578
+ return fragment;
579
+ };
580
+
581
+ const wordListLevel: (element: Element) => number = (
582
+ element: Element,
583
+ ): number => {
584
+ if (tagOf(element) !== "p") {
585
+ return 0;
586
+ }
587
+ const match: RegExpMatchArray | null = (
588
+ element.getAttribute("style") || ""
589
+ ).match(RE_WORD_LIST_STYLE);
590
+ return match ? parseInt(match[1] || "1", 10) : 0;
591
+ };
592
+
593
+ // The next element sibling, stepping over whitespace and comments only.
594
+ const nextElementOnlyAfterGap: (node: Element) => Element | null = (
595
+ node: Element,
596
+ ): Element | null => {
597
+ let next: ChildNode | null = node.nextSibling;
598
+ while (next) {
599
+ if (next.nodeType === Node.ELEMENT_NODE) {
600
+ return next as Element;
601
+ }
602
+ if (
603
+ next.nodeType === Node.TEXT_NODE &&
604
+ RE_NOT_WHITESPACE.test((next.textContent || "").replace(RE_NBSP, ""))
605
+ ) {
606
+ return null;
607
+ }
608
+ next = next.nextSibling;
609
+ }
610
+ return null;
611
+ };
612
+
613
+ const rebuildWordListParagraphs: (body: HTMLElement) => void = (
614
+ body: HTMLElement,
615
+ ): void => {
616
+ const doc: Document = body.ownerDocument;
617
+ for (const paragraph of elementsOf(body, "p[style]")) {
618
+ if (!paragraph.isConnected || wordListLevel(paragraph) === 0) {
619
+ continue;
620
+ }
621
+ const run: Array<HTMLElement> = [paragraph];
622
+ let next: Element | null = nextElementOnlyAfterGap(paragraph);
623
+ while (next && wordListLevel(next) > 0) {
624
+ run.push(next as HTMLElement);
625
+ next = nextElementOnlyAfterGap(next);
626
+ }
627
+ const entries: Array<NestedListEntry> = run.map(
628
+ (item: HTMLElement): NestedListEntry => {
629
+ const marker: string = takeWordListMarker(item);
630
+ return {
631
+ depth: wordListLevel(item) - 1,
632
+ ordered: RE_WORD_ORDERED_MARKER.test(marker.replace(/\s+/g, "")),
633
+ content: Array.from(item.childNodes),
634
+ };
635
+ },
636
+ );
637
+ const first: HTMLElement = run[0] as HTMLElement;
638
+ first.parentNode?.insertBefore(buildNestedLists(doc, entries), first);
639
+ run.forEach((item: HTMLElement, position: number): void => {
640
+ // The whitespace between two of the paragraphs goes with them.
641
+ let gap: ChildNode | null = position > 0 ? item.previousSibling : null;
642
+ while (gap && gap.nodeType !== Node.ELEMENT_NODE) {
643
+ const before: ChildNode | null = gap.previousSibling;
644
+ gap.remove();
645
+ gap = before;
646
+ }
647
+ item.remove();
648
+ });
649
+ }
650
+ // Markers Word left anywhere else (a list written as <li>s, say).
651
+ for (const element of elementsOf(body, "li, p")) {
652
+ if (
653
+ commentsOf(element).length > 0 ||
654
+ element.querySelector("span[style]")
655
+ ) {
656
+ takeWordListMarker(element);
657
+ }
658
+ }
659
+ };
660
+
661
+ /*
662
+ * ---- 3. Formatting written as styles (Google Docs, Word, browsers) --------
663
+ */
664
+
665
+ const wrapIn: (element: Element, tag: string) => void = (
666
+ element: Element,
667
+ tag: string,
668
+ ): void => {
669
+ const wrapper: HTMLElement = element.ownerDocument.createElement(tag);
670
+ element.parentNode?.insertBefore(wrapper, element);
671
+ wrapper.appendChild(element);
672
+ };
673
+
674
+ const readStyledFormatting: (body: HTMLElement) => void = (
675
+ body: HTMLElement,
676
+ ): void => {
677
+ /*
678
+ * Google Docs wraps the whole copy in <b style="font-weight:normal"
679
+ * id="docs-internal-guid-...">. Taken at its tag, the entire paste came
680
+ * out as one bold run with stray "**" lines around it. A <b> or <strong>
681
+ * whose own style says normal weight is not bold either.
682
+ */
683
+ for (const element of elementsOf(body, "b, strong")) {
684
+ if (
685
+ RE_DOCS_GUID.test(element.id) ||
686
+ isNormalWeight(element.style.fontWeight)
687
+ ) {
688
+ unwrap(element);
689
+ }
690
+ }
691
+ /*
692
+ * Docs, and a browser copying part of a styled element, write formatting
693
+ * as span styles rather than tags. Only the three kinds markdown has are
694
+ * read, and only where the text is not already inside that formatting.
695
+ */
696
+ for (const span of elementsOf(body, "span[style], font[style]")) {
697
+ const style: CSSStyleDeclaration = span.style;
698
+ const decoration: string = `${style.textDecorationLine || ""} ${style.textDecoration || ""}`;
699
+ if (
700
+ decoration.includes("line-through") &&
701
+ !span.closest("s, del, strike")
702
+ ) {
703
+ wrapIn(span, "s");
704
+ }
705
+ if (
706
+ (style.fontStyle === "italic" || style.fontStyle === "oblique") &&
707
+ !span.closest("em, i")
708
+ ) {
709
+ wrapIn(span, "em");
710
+ }
711
+ if (
712
+ isBoldWeight(style.fontWeight) &&
713
+ !span.closest("strong, b, h1, h2, h3, h4, h5, h6, th")
714
+ ) {
715
+ wrapIn(span, "strong");
716
+ }
717
+ }
718
+ };
719
+
720
+ /*
721
+ * ---- 4. What MarkdownViewer renders ---------------------------------------
722
+ */
723
+
724
+ /*
725
+ * The text of a preformatted element, with a line break for each <br> and
726
+ * for each block inside it -- an editor that writes one <div> per line.
727
+ */
728
+ const preformattedText: (element: Element) => string = (
729
+ element: Element,
730
+ ): string => {
731
+ let text: string = "";
732
+ const walk: (node: Node) => void = (node: Node): void => {
733
+ for (const child of Array.from(node.childNodes)) {
734
+ if (child.nodeType === Node.TEXT_NODE) {
735
+ text += (child as Text).data;
736
+ } else if (tagOf(child) === "br") {
737
+ text += "\n";
738
+ } else if (child.nodeType === Node.ELEMENT_NODE) {
739
+ const block: boolean = isBlock(child);
740
+ if (block && text.length > 0 && !text.endsWith("\n")) {
741
+ text += "\n";
742
+ }
743
+ walk(child);
744
+ if (block && !text.endsWith("\n")) {
745
+ text += "\n";
746
+ }
747
+ }
748
+ }
749
+ };
750
+ walk(element);
751
+ return text;
752
+ };
753
+
754
+ const restoreViewerMarkup: (body: HTMLElement) => void = (
755
+ body: HTMLElement,
756
+ ): void => {
757
+ const doc: Document = body.ownerDocument;
758
+ /*
759
+ * A code block renders as a syntax-highlighted <div> with no <pre> and no
760
+ * language class, so on its own it would paste as highlighted spans of
761
+ * plain text. The viewer marks its root with the language instead.
762
+ */
763
+ for (const block of elementsOf(body, "[data-markdown-code-block]")) {
764
+ if (!block.isConnected) {
765
+ continue;
766
+ }
767
+ const language: string = (block.getAttribute("data-language") || "").trim();
768
+ const source: Element = block.querySelector("code") || block;
769
+ const text: string = preformattedText(source);
770
+ /*
771
+ * Only the <pre> the code is in reached the clipboard -- the copy began
772
+ * and ended inside the code -- and it holds no line break: a
773
+ * double-clicked word, part of a command. Every browser keeps that <pre>
774
+ * around even a word, and as a fenced block the word split the sentence
775
+ * it was pasted into (the visual editor) or ran into the rest of the
776
+ * line (the markdown source), where the closing fence opened a new one
777
+ * that swallowed the rest of the note. It is inline code instead. A copy
778
+ * with a line break in it -- lines, or a line Chromium or Safari
779
+ * triple-clicks, break and all -- and one that carries the block's own
780
+ * root, all of the block, stay fenced blocks; so does text holding a
781
+ * backtick, which inline code would cut short.
782
+ */
783
+ if (
784
+ tagOf(block) === "pre" &&
785
+ !text.includes("\n") &&
786
+ !text.includes("`") &&
787
+ RE_NOT_WHITESPACE.test(text)
788
+ ) {
789
+ const inline: HTMLElement = doc.createElement("code");
790
+ inline.textContent = text;
791
+ block.parentNode?.insertBefore(inline, block);
792
+ block.remove();
793
+ continue;
794
+ }
795
+ const code: HTMLElement = doc.createElement("code");
796
+ if (language && language !== "text" && RE_LANGUAGE.test(language)) {
797
+ code.className = `language-${language}`;
798
+ }
799
+ code.textContent = text;
800
+ const pre: HTMLElement = doc.createElement("pre");
801
+ pre.appendChild(code);
802
+ block.parentNode?.insertBefore(pre, block);
803
+ block.remove();
804
+ }
805
+ /*
806
+ * A timestamp the viewer localized ("Apr 20, 2026 11:21 AM" for the
807
+ * reader) came from an inline-code ISO timestamp, which is what is put
808
+ * back, so it is localized again for whoever reads the new note.
809
+ */
810
+ for (const time of elementsOf(body, "time[datetime]")) {
811
+ const iso: string = (time.getAttribute("datetime") || "").trim();
812
+ if (RE_VIEWER_TIMESTAMP.test(iso)) {
813
+ const code: HTMLElement = doc.createElement("code");
814
+ code.textContent = iso;
815
+ time.parentNode?.insertBefore(code, time);
816
+ time.remove();
817
+ }
818
+ }
819
+ };
820
+
821
+ /*
822
+ * ---- 5. Links and images ---------------------------------------------------
823
+ */
824
+
825
+ /*
826
+ * The URL with its scheme checked against `schemes`, or null when it is not
827
+ * allowed. Browsers ignore control characters and whitespace in a scheme
828
+ * ("java\tscript:"), so they are dropped before the check. Scheme-less URLs
829
+ * (relative, or "//host/path") are allowed. Spaces and parentheses are
830
+ * encoded: either one ends a markdown link's URL early.
831
+ */
832
+ const safeUrl: (raw: string, schemes: Array<string>) => string | null = (
833
+ raw: string,
834
+ schemes: Array<string>,
835
+ ): string | null => {
836
+ let url: string = "";
837
+ for (const ch of raw) {
838
+ const code: number = ch.charCodeAt(0);
839
+ if (code >= 0x20 && code !== 0x7f) {
840
+ url += ch;
841
+ }
842
+ }
843
+ url = url.trim();
844
+ if (!url) {
845
+ return null;
846
+ }
847
+ const scheme: RegExpMatchArray | null = url
848
+ .replace(/\s+/g, "")
849
+ .match(RE_URL_SCHEME);
850
+ if (scheme && !schemes.includes((scheme[1] || "").toLowerCase())) {
851
+ return null;
852
+ }
853
+ return url.replace(RE_URL_BREAKING, (ch: string): string => {
854
+ return encodeURIComponent(ch) === ch
855
+ ? `%${ch.charCodeAt(0).toString(16).toUpperCase()}`
856
+ : encodeURIComponent(ch);
857
+ });
858
+ };
859
+
860
+ /*
861
+ * SessionAwareImage retries a private image with a "sessionRetry" cache
862
+ * buster; a copy of the rendered note carries it along, and it means nothing
863
+ * in the new one.
864
+ */
865
+ const withoutSessionRetry: (url: string) => string = (url: string): string => {
866
+ return url.replace(
867
+ RE_SESSION_RETRY,
868
+ (_match: string, separator: string, more: string): string => {
869
+ return more ? separator : "";
870
+ },
871
+ );
872
+ };
873
+
874
+ const sanitizeLinksAndImages: (body: HTMLElement) => void = (
875
+ body: HTMLElement,
876
+ ): void => {
877
+ for (const link of elementsOf(body, "a[href]")) {
878
+ const href: string | null = safeUrl(
879
+ link.getAttribute("href") || "",
880
+ LINK_SCHEMES,
881
+ );
882
+ if (href === null) {
883
+ unwrap(link);
884
+ } else {
885
+ link.setAttribute("href", href);
886
+ }
887
+ }
888
+ for (const image of elementsOf(body, "img")) {
889
+ const src: string | null = safeUrl(
890
+ withoutSessionRetry(image.getAttribute("src") || ""),
891
+ IMAGE_SCHEMES,
892
+ );
893
+ if (src === null) {
894
+ // data:, blob:, file: and cid: images are not uploaded -- dropped.
895
+ image.remove();
896
+ continue;
897
+ }
898
+ image.setAttribute("src", src);
899
+ image.setAttribute(
900
+ "alt",
901
+ (image.getAttribute("alt") || "").replace(/[[\]\s]+/g, " ").trim(),
902
+ );
903
+ image.removeAttribute("title");
904
+ }
905
+ /*
906
+ * A link left with nothing to read -- the permalink icon GitHub puts
907
+ * beside every heading, a row of social icons, once their <svg>s are gone,
908
+ * or the empty or zero-width-space anchors of GitLab and Docusaurus --
909
+ * would be written out with its URL as its text: every heading copied from
910
+ * a README gained a line of "[https://github.com/...#install](...)". It is
911
+ * not content, so it is unwrapped. Whatever space it held stays, so the
912
+ * words either side of it do not run together. The URLs browsers put on
913
+ * the clipboard are absolute, so the link is known by its emptiness, not
914
+ * by an href starting with "#". This runs after the images are checked,
915
+ * so a link whose only image was dropped goes too.
916
+ */
917
+ for (const link of elementsOf(body, "a[href]")) {
918
+ const text: string = (link.textContent || "")
919
+ .replace(RE_NBSP, "")
920
+ .replace(RE_ZERO_WIDTH, "");
921
+ if (RE_NOT_WHITESPACE.test(text) || link.querySelector("img")) {
922
+ continue;
923
+ }
924
+ for (const node of textNodesOf(link)) {
925
+ node.data = node.data.replace(RE_ZERO_WIDTH, "");
926
+ }
927
+ unwrap(link);
928
+ }
929
+ };
930
+
931
+ /*
932
+ * ---- 6. Lists --------------------------------------------------------------
933
+ */
934
+
935
+ /*
936
+ * Outlook, and every browser's execCommand("indent"), write a nested list
937
+ * as a <ul> directly inside a <ul> -- invalid, and the serializer, which
938
+ * reads only a list's <li> children, dropped it and everything in it. It is
939
+ * moved into the item before it, as markdown nests it. Anything else loose
940
+ * in a list is wrapped in an item of its own rather than lost.
941
+ */
942
+ const repairLists: (body: HTMLElement) => void = (body: HTMLElement): void => {
943
+ const doc: Document = body.ownerDocument;
944
+ for (const list of elementsOf(body, "ul, ol")) {
945
+ let loose: HTMLElement | null = null;
946
+ for (const child of Array.from(list.childNodes)) {
947
+ if (child.nodeType === Node.COMMENT_NODE) {
948
+ continue;
949
+ }
950
+ if (
951
+ child.nodeType === Node.TEXT_NODE &&
952
+ !RE_NOT_WHITESPACE.test((child.textContent || "").replace(RE_NBSP, ""))
953
+ ) {
954
+ child.remove();
955
+ continue;
956
+ }
957
+ if (tagOf(child) === "li") {
958
+ loose = null;
959
+ continue;
960
+ }
961
+ if (isList(child)) {
962
+ const previous: Element | null = (child as Element)
963
+ .previousElementSibling;
964
+ if (previous && tagOf(previous) === "li") {
965
+ previous.appendChild(child);
966
+ loose = null;
967
+ continue;
968
+ }
969
+ }
970
+ if (!loose) {
971
+ loose = doc.createElement("li");
972
+ list.insertBefore(loose, child);
973
+ }
974
+ loose.appendChild(child);
975
+ }
976
+ }
977
+ /*
978
+ * Google Docs puts each item's text in a <p>, which made every item a
979
+ * separate paragraph -- a blank line inside the item. An item with a
980
+ * single paragraph is tight, so the paragraph goes.
981
+ */
982
+ for (const item of elementsOf(body, "li")) {
983
+ const paragraphs: Array<Element> = Array.from(item.children).filter(
984
+ (child: Element): boolean => {
985
+ return tagOf(child) === "p";
986
+ },
987
+ );
988
+ if (paragraphs.length === 1 && paragraphs[0]) {
989
+ unwrap(paragraphs[0]);
990
+ }
991
+ }
992
+ };
993
+
994
+ /*
995
+ * ---- 7. Whitespace ---------------------------------------------------------
996
+ */
997
+
998
+ // A sibling that renders as nothing: a comment, or text that is only whitespace.
999
+ const rendersNothing: (node: Node) => boolean = (node: Node): boolean => {
1000
+ return (
1001
+ node.nodeType === Node.COMMENT_NODE ||
1002
+ (node.nodeType === Node.TEXT_NODE &&
1003
+ !RE_NOT_WHITESPACE.test((node.textContent || "").replace(RE_NBSP, "")))
1004
+ );
1005
+ };
1006
+
1007
+ // Whether `node` is the last thing in its block (or comes right before a block or a <br>).
1008
+ const endsBlock: (node: Node) => boolean = (node: Node): boolean => {
1009
+ let current: Node = node;
1010
+ for (;;) {
1011
+ let next: Node | null = current.nextSibling;
1012
+ while (next && rendersNothing(next)) {
1013
+ next = next.nextSibling;
1014
+ }
1015
+ if (next) {
1016
+ return isBlock(next);
1017
+ }
1018
+ const parent: Node | null = current.parentNode;
1019
+ if (!parent || isBlock(parent) || parent.nodeType !== Node.ELEMENT_NODE) {
1020
+ return true;
1021
+ }
1022
+ current = parent;
1023
+ }
1024
+ };
1025
+
1026
+ /*
1027
+ * HTML ignores the line breaks and runs of spaces in its source; markdown
1028
+ * does not. Word hard-wraps its HTML ("Service\n is currently
1029
+ * unavailable"), so without this a pasted item came back as two lines.
1030
+ * Walking the text in order, a space is dropped where the browser would not
1031
+ * show one: at the start or end of a block, beside a <br>, and after a space
1032
+ * already written. Text in a <pre> is left exactly as it is.
1033
+ */
1034
+ const collapseWhitespace: (body: HTMLElement) => void = (
1035
+ body: HTMLElement,
1036
+ ): void => {
1037
+ // Whether the text so far ends in a space, or a block has just begun.
1038
+ let atSpace: boolean = true;
1039
+ const walk: (node: Node) => void = (node: Node): void => {
1040
+ for (const child of Array.from(node.childNodes)) {
1041
+ if (child.nodeType === Node.TEXT_NODE) {
1042
+ const text: Text = child as Text;
1043
+ let value: string = text.data
1044
+ .replace(RE_NBSP, " ")
1045
+ .replace(RE_WHITESPACE_RUN, " ");
1046
+ if (atSpace && value.startsWith(" ")) {
1047
+ value = value.slice(1);
1048
+ }
1049
+ if (value.endsWith(" ") && endsBlock(text)) {
1050
+ value = value.slice(0, -1);
1051
+ }
1052
+ if (value.length === 0) {
1053
+ text.remove();
1054
+ continue;
1055
+ }
1056
+ text.data = value;
1057
+ atSpace = value.endsWith(" ");
1058
+ continue;
1059
+ }
1060
+ if (child.nodeType !== Node.ELEMENT_NODE) {
1061
+ continue;
1062
+ }
1063
+ const tag: string = tagOf(child);
1064
+ if (tag === "pre") {
1065
+ atSpace = true;
1066
+ } else if (isBlock(child)) {
1067
+ atSpace = true;
1068
+ walk(child);
1069
+ atSpace = true;
1070
+ } else if (tag === "img" || tag === "input") {
1071
+ atSpace = false;
1072
+ } else {
1073
+ walk(child);
1074
+ }
1075
+ }
1076
+ };
1077
+ walk(body);
1078
+ };
1079
+
1080
+ /*
1081
+ * "**bold **text" is not bold in CommonMark -- a closing "**" after a space
1082
+ * does not close anything -- so whitespace at either edge of a formatting
1083
+ * element moves outside it. A formatting element with no text at all would
1084
+ * come out as "****" and is replaced by the whitespace it held, if any.
1085
+ * Runs before the whitespace is collapsed, which tidies what this moves.
1086
+ */
1087
+ const tidyInlineFormatting: (body: HTMLElement) => void = (
1088
+ body: HTMLElement,
1089
+ ): void => {
1090
+ const doc: Document = body.ownerDocument;
1091
+ for (const element of elementsOf(
1092
+ body,
1093
+ INLINE_FORMATTING_SELECTOR,
1094
+ ).reverse()) {
1095
+ const parent: ParentNode | null = element.parentNode;
1096
+ if (!parent) {
1097
+ continue;
1098
+ }
1099
+ const content: string = element.textContent || "";
1100
+ if (!RE_NOT_WHITESPACE.test(content) && !element.querySelector("img, br")) {
1101
+ if (content) {
1102
+ parent.insertBefore(doc.createTextNode(" "), element);
1103
+ }
1104
+ element.remove();
1105
+ continue;
1106
+ }
1107
+ const texts: Array<Text> = textNodesOf(element);
1108
+ const first: Text | undefined = texts[0];
1109
+ const last: Text | undefined = texts[texts.length - 1];
1110
+ if (first && RE_LEADING_SPACE.test(first.data)) {
1111
+ first.data = first.data.replace(RE_LEADING_SPACE, "");
1112
+ parent.insertBefore(doc.createTextNode(" "), element);
1113
+ }
1114
+ if (last && RE_TRAILING_SPACE.test(last.data)) {
1115
+ last.data = last.data.replace(RE_TRAILING_SPACE, "");
1116
+ parent.insertBefore(doc.createTextNode(" "), element.nextSibling);
1117
+ }
1118
+ }
1119
+ body.normalize();
1120
+ };
1121
+
1122
+ /*
1123
+ * ---------------------------------------------------------------------------
1124
+ * Pipeline
1125
+ * ---------------------------------------------------------------------------
1126
+ */
1127
+
1128
+ /*
1129
+ * A <div> that keeps its whitespace ("white-space: pre") is what code
1130
+ * editors put on the clipboard -- VS Code writes one such <div> holding a
1131
+ * <div> of coloured spans per line. Its plain text is the real content
1132
+ * (often markdown source itself), so that is what gets pasted, as before.
1133
+ *
1134
+ * So is a table cell that keeps its whitespace: a code view drawn as a
1135
+ * table, one row per line beside a column of line numbers, as OneUptime's
1136
+ * own Kubernetes YAML tab and exception stack frames are. Chromium and
1137
+ * Safari write the cell's white-space on every cell they copy. Not counted,
1138
+ * lines of YAML copied there pasted as a one-column table with the first
1139
+ * line as its header and the indentation gone.
1140
+ *
1141
+ * Only those count, and not inside a <pre> or a list item. Google Docs puts
1142
+ * "white-space:pre" on every list item it copies, and Chromium, Safari and
1143
+ * Docs wrap each tab in a <span class="Apple-tab-span"> styled the same
1144
+ * way; taken for a code editor's copy, any Docs copy with a list or a tab
1145
+ * lost its lists, links and formatting to its plain text -- bare lines.
1146
+ */
1147
+ const isCodeEditorCopy: (body: HTMLElement) => boolean = (
1148
+ body: HTMLElement,
1149
+ ): boolean => {
1150
+ return elementsOf(body, "div[style], td[style], th[style]").some(
1151
+ (element: HTMLElement): boolean => {
1152
+ return element.style.whiteSpace === "pre" && !element.closest("pre, li");
1153
+ },
1154
+ );
1155
+ };
1156
+
1157
+ const parseInertly: (html: string) => HTMLElement | null = (
1158
+ html: string,
1159
+ ): HTMLElement | null => {
1160
+ if (typeof DOMParser === "undefined") {
1161
+ return null;
1162
+ }
1163
+ return new DOMParser().parseFromString(html, "text/html").body;
1164
+ };
1165
+
1166
+ // The clipboard HTML parsed and cleaned, ready for the serializer.
1167
+ const cleanPastedHtml: (html: string) => HTMLElement | null = (
1168
+ html: string,
1169
+ ): HTMLElement | null => {
1170
+ if (!html) {
1171
+ return null;
1172
+ }
1173
+ const body: HTMLElement | null = parseInertly(html);
1174
+ if (!body) {
1175
+ return null;
1176
+ }
1177
+ removeNonContent(body);
1178
+ rebuildWordListParagraphs(body);
1179
+ readStyledFormatting(body);
1180
+ restoreViewerMarkup(body);
1181
+ sanitizeLinksAndImages(body);
1182
+ repairLists(body);
1183
+ tidyInlineFormatting(body);
1184
+ collapseWhitespace(body);
1185
+ return body;
1186
+ };
1187
+
1188
+ const hasRichContent: (body: HTMLElement) => boolean = (
1189
+ body: HTMLElement,
1190
+ ): boolean => {
1191
+ return (
1192
+ body.querySelector(RICH_CONTENT_SELECTOR) !== null &&
1193
+ !isCodeEditorCopy(body)
1194
+ );
1195
+ };
1196
+
1197
+ const hasText: (body: HTMLElement) => boolean = (
1198
+ body: HTMLElement,
1199
+ ): boolean => {
1200
+ return RE_NOT_WHITESPACE.test(body.textContent || "");
1201
+ };
1202
+
1203
+ /*
1204
+ * Whether clipboard HTML carries structure or formatting its plain text
1205
+ * loses -- lists, headings, links, emphasis, tables, code, images -- and so
1206
+ * is worth converting. A plain paragraph is not: its plain text says the
1207
+ * same, and is what the editor has always pasted.
1208
+ */
1209
+ export const isRichClipboardHtml: (html: string) => boolean = (
1210
+ html: string,
1211
+ ): boolean => {
1212
+ const body: HTMLElement | null = cleanPastedHtml(html);
1213
+ return body !== null && hasRichContent(body);
1214
+ };
1215
+
1216
+ // Clipboard HTML as the markdown the editor writes.
1217
+ export const pastedHtmlToMarkdown: (html: string) => string = (
1218
+ html: string,
1219
+ ): string => {
1220
+ const body: HTMLElement | null = cleanPastedHtml(html);
1221
+ return body ? domToMarkdown(body) : "";
1222
+ };
1223
+
1224
+ const readClipboard: (clipboard: PastedClipboard, format: string) => string = (
1225
+ clipboard: PastedClipboard,
1226
+ format: string,
1227
+ ): string => {
1228
+ try {
1229
+ return clipboard.getData(format) || "";
1230
+ } catch {
1231
+ return "";
1232
+ }
1233
+ };
1234
+
1235
+ // Whether a DataTransfer's `types` (an array, or a DOMStringList in older browsers) lists `format`.
1236
+ const listsType: (
1237
+ types: ReadonlyArray<string> | undefined,
1238
+ format: string,
1239
+ ) => boolean = (
1240
+ types: ReadonlyArray<string> | undefined,
1241
+ format: string,
1242
+ ): boolean => {
1243
+ if (!types) {
1244
+ return false;
1245
+ }
1246
+ for (let i: number = 0; i < types.length; i++) {
1247
+ if (types[i] === format) {
1248
+ return true;
1249
+ }
1250
+ }
1251
+ return false;
1252
+ };
1253
+
1254
+ const RE_STARTS_WITH_SPACE: RegExp = /^[ \t]/;
1255
+ const RE_ENDS_WITH_SPACE: RegExp = /[ \t]$/;
1256
+
1257
+ /*
1258
+ * A few words copied out of a line ("very " with its space) are pasted into
1259
+ * the middle of another, where the space between them and the next word
1260
+ * matters -- but as HTML the space sits at the edge of the document, where
1261
+ * it is trimmed like any block's. When the converted text is a single line,
1262
+ * the spaces at the plain text's edges are put back.
1263
+ */
1264
+ const withEdgeSpacesOf: (plain: string, markdown: string) => string = (
1265
+ plain: string,
1266
+ markdown: string,
1267
+ ): string => {
1268
+ if (!markdown || markdown.includes("\n")) {
1269
+ return markdown;
1270
+ }
1271
+ const leading: string = RE_STARTS_WITH_SPACE.test(plain) ? " " : "";
1272
+ const trailing: string = RE_ENDS_WITH_SPACE.test(plain) ? " " : "";
1273
+ return `${leading}${markdown}${trailing}`;
1274
+ };
1275
+
1276
+ /*
1277
+ * The markdown to paste, or null to leave the paste to the caller -- to
1278
+ * upload the image files on the clipboard, or to let the browser do what it
1279
+ * does natively.
1280
+ *
1281
+ * Rich HTML with text in it wins, even over image files: Word and Excel put
1282
+ * a picture of the copied text on the clipboard beside the text itself.
1283
+ * HTML that is nothing but images ("Copy image" in a browser) gives way to
1284
+ * the files, since an upload beats a link to someone else's server; so does
1285
+ * plain text, which beside a file is its name (a file copied in Finder).
1286
+ * Otherwise the plain text is used, with other apps' bullets made markdown.
1287
+ */
1288
+ export const clipboardToMarkdown: (
1289
+ clipboard: PastedClipboard,
1290
+ options?: ClipboardToMarkdownOptions,
1291
+ ) => string | null = (
1292
+ clipboard: PastedClipboard,
1293
+ options?: ClipboardToMarkdownOptions,
1294
+ ): string | null => {
1295
+ const preferFiles: boolean =
1296
+ options?.hasImageFiles ?? listsType(clipboard.types, "Files");
1297
+ // Line breaks as a textarea holds them, so a caller can compare the two.
1298
+ const plain: string = readClipboard(clipboard, "text/plain").replace(
1299
+ RE_LINE_BREAKS,
1300
+ "\n",
1301
+ );
1302
+
1303
+ const html: string = readClipboard(clipboard, "text/html");
1304
+ const body: HTMLElement | null = cleanPastedHtml(html);
1305
+ if (body && hasRichContent(body)) {
1306
+ const markdown: string = withEdgeSpacesOf(plain, domToMarkdown(body));
1307
+ if (hasText(body)) {
1308
+ return markdown;
1309
+ }
1310
+ if (!preferFiles && markdown) {
1311
+ return markdown;
1312
+ }
1313
+ }
1314
+
1315
+ if (preferFiles) {
1316
+ return null;
1317
+ }
1318
+
1319
+ if (plain) {
1320
+ return normalizePlainTextListMarkers(plain);
1321
+ }
1322
+ if (body && hasText(body)) {
1323
+ return domToMarkdown(body);
1324
+ }
1325
+ return null;
1326
+ };