@oneuptime/common 12.0.6 → 12.0.7

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 (424) hide show
  1. package/Models/DatabaseModels/AIInsight.ts +1 -1
  2. package/Models/DatabaseModels/DatabaseBaseModel/FileModel.ts +2 -3
  3. package/Models/DatabaseModels/DeletedProject.ts +595 -0
  4. package/Models/DatabaseModels/Index.ts +2 -0
  5. package/Models/DatabaseModels/Monitor.ts +111 -0
  6. package/Models/DatabaseModels/Project.ts +3 -3
  7. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -1
  8. package/Server/API/FileAPI.ts +15 -2
  9. package/Server/API/MicrosoftTeamsAPI.ts +6 -1
  10. package/Server/API/ProjectAPI.ts +214 -0
  11. package/Server/API/StatusPageAPI.ts +39 -6
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.ts +50 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.ts +67 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.ts +39 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  16. package/Server/Services/AIAgentService.ts +20 -0
  17. package/Server/Services/DashboardDomainService.ts +73 -28
  18. package/Server/Services/DatabaseService.ts +1 -0
  19. package/Server/Services/DeletedProjectService.ts +138 -0
  20. package/Server/Services/FileService.ts +61 -0
  21. package/Server/Services/IncidentEpisodePublicNoteService.ts +18 -0
  22. package/Server/Services/IncidentPublicNoteService.ts +18 -0
  23. package/Server/Services/Index.ts +2 -0
  24. package/Server/Services/MonitorService.ts +311 -0
  25. package/Server/Services/ProbeService.ts +20 -0
  26. package/Server/Services/ProjectService.ts +297 -1
  27. package/Server/Services/PushNotificationService.ts +71 -0
  28. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +18 -0
  29. package/Server/Services/StatusPageAnnouncementService.ts +53 -0
  30. package/Server/Services/StatusPageDomainService.ts +73 -28
  31. package/Server/Services/TeamMemberService.ts +117 -12
  32. package/Server/Services/TelemetryIngestionKeyService.ts +1 -0
  33. package/Server/Services/UserWebhookService.ts +34 -109
  34. package/Server/Services/WorkspaceNotificationRuleService.ts +69 -0
  35. package/Server/Services/WorkspaceProjectAuthTokenService.ts +37 -1
  36. package/Server/Types/Database/DeleteById.ts +2 -0
  37. package/Server/Types/Database/DeleteOneBy.ts +6 -0
  38. package/Server/Types/Domain.ts +41 -0
  39. package/Server/Types/Workflow/Components/API/Delete.ts +2 -1
  40. package/Server/Types/Workflow/Components/API/Get.ts +2 -1
  41. package/Server/Types/Workflow/Components/API/Patch.ts +2 -1
  42. package/Server/Types/Workflow/Components/API/Post.ts +2 -1
  43. package/Server/Types/Workflow/Components/API/Put.ts +2 -1
  44. package/Server/Types/Workflow/Components/API/Utils.ts +41 -2
  45. package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +25 -19
  46. package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +6 -5
  47. package/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.ts +32 -14
  48. package/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts +31 -13
  49. package/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts +29 -20
  50. package/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts +28 -21
  51. package/Server/Types/Workflow/Components/BaseModel/LogComponentError.ts +89 -0
  52. package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +208 -0
  53. package/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts +11 -0
  54. package/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts +41 -18
  55. package/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts +45 -19
  56. package/Server/Types/Workflow/Components/Discord/SendMessageToChannel.ts +16 -9
  57. package/Server/Types/Workflow/Components/IncomingWebhookUtils.ts +66 -0
  58. package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +15 -9
  59. package/Server/Types/Workflow/Components/Slack/SendMessageToChannel.ts +17 -0
  60. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
  61. package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +171 -0
  62. package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +3 -3
  63. package/Server/Utils/AI/SRE/Insights/FixRouting.ts +3 -2
  64. package/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.ts +1 -1
  65. package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +6 -6
  66. package/Server/Utils/CodeRepository/GitHub/GitHub.ts +43 -5
  67. package/Server/Utils/DataSource/EgressGuard.ts +176 -16
  68. package/Server/Utils/DataSource/HttpFetch.ts +6 -45
  69. package/Server/Utils/Execute.ts +8 -0
  70. package/Server/Utils/InlineImageAccessTokenSync.ts +23 -0
  71. package/Server/Utils/LLM/LLMService.ts +57 -12
  72. package/Server/Utils/Monitor/MonitorAlert.ts +40 -0
  73. package/Server/Utils/Monitor/MonitorDependencySuppression.ts +192 -0
  74. package/Server/Utils/Monitor/MonitorIncident.ts +40 -0
  75. package/Server/Utils/Monitor/MonitorResource.ts +36 -0
  76. package/Server/Utils/Response.ts +142 -6
  77. package/Server/Utils/SSRFProtection.ts +273 -60
  78. package/Server/Utils/StartServer.ts +8 -0
  79. package/Server/Utils/VM/VMRunner.ts +88 -1
  80. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +555 -49
  81. package/Server/Utils/Workspace/Slack/Slack.ts +25 -2
  82. package/Server/Utils/Workspace/WorkspaceBase.ts +6 -0
  83. package/Tests/App/Dashboard/DangerZone.test.tsx +334 -0
  84. package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +539 -0
  85. package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +678 -0
  86. package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +706 -0
  87. package/Tests/App/Dashboard/DashboardVariablesModal.test.tsx +508 -0
  88. package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +470 -0
  89. package/Tests/App/StatusPage/StatusPageDetailPagesNotFound.test.tsx +308 -0
  90. package/Tests/Models/DatabaseModels/DeletedProjectModel.test.ts +251 -0
  91. package/Tests/Models/DatabaseModels/SavedViewJSONColumnTuples.test.ts +115 -0
  92. package/Tests/Server/API/FileAPIAccessControl.test.ts +316 -0
  93. package/Tests/Server/API/ProjectAPI.test.ts +299 -1
  94. package/Tests/Server/API/ProjectAPIAdjustBalance.test.ts +459 -0
  95. package/Tests/Server/API/ProjectAPIAdjustBalanceBillingDisabled.test.ts +177 -0
  96. package/Tests/Server/Services/DatabaseServiceDeletionReason.test.ts +123 -0
  97. package/Tests/Server/Services/DeletedProjectService.test.ts +415 -0
  98. package/Tests/Server/Services/DeletedProjectServiceSelfHosted.test.ts +70 -0
  99. package/Tests/Server/Services/DomainSubdomainHooks.test.ts +94 -0
  100. package/Tests/Server/Services/FileIsPublicBooleanMigration.test.ts +244 -0
  101. package/Tests/Server/Services/FileServiceMimeType.test.ts +89 -0
  102. package/Tests/Server/Services/MonitorServiceDependencyValidation.test.ts +702 -0
  103. package/Tests/Server/Services/ProjectServiceAdjustBalance.test.ts +615 -0
  104. package/Tests/Server/Services/ProjectServiceDeleteAudit.test.ts +406 -0
  105. package/Tests/Server/Services/PublishTimeImageVisibility.test.ts +450 -0
  106. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +669 -0
  107. package/Tests/Server/Services/UserWebhookSSRF.test.ts +174 -0
  108. package/Tests/Server/Services/WebPushEndpointAllowlist.test.ts +133 -0
  109. package/Tests/Server/Services/WorkspaceProjectAuthTokenRepoint.test.ts +618 -0
  110. package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +26 -1
  111. package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +215 -0
  112. package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +742 -0
  113. package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +256 -0
  114. package/Tests/Server/Types/Workflow/Components/ModelArguments.test.ts +371 -0
  115. package/Tests/Server/Utils/AI/CodeAgentCommandGuard.test.ts +204 -0
  116. package/Tests/Server/Utils/AI/CodeAgentWriteLimits.test.ts +213 -0
  117. package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +52 -5
  118. package/Tests/Server/Utils/AI/LLMServiceBaseUrl.test.ts +3 -0
  119. package/Tests/Server/Utils/AI/LLMServiceEgressGuard.test.ts +315 -0
  120. package/Tests/Server/Utils/AI/LLMServiceModelCompatibility.test.ts +3 -0
  121. package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +17 -5
  122. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +14 -1
  123. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +35 -0
  124. package/Tests/Server/Utils/AI/StubLLMEgressGuard.ts +25 -0
  125. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +62 -7
  126. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +69 -0
  127. package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +330 -0
  128. package/Tests/Server/Utils/GitHubCreatePullRequestWithToken.test.ts +393 -0
  129. package/Tests/Server/Utils/InlineImageAccessTokenSync.test.ts +202 -0
  130. package/Tests/Server/Utils/Monitor/MonitorDependencySuppression.test.ts +811 -0
  131. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +604 -0
  132. package/Tests/Server/Utils/ResponseSendFileResponse.test.ts +192 -0
  133. package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +406 -0
  134. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +194 -0
  135. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +1169 -0
  136. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +2 -0
  137. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +1605 -0
  138. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTenantResolution.test.ts +1218 -0
  139. package/Tests/Types/AI/AIChatMessageStatus.test.ts +79 -0
  140. package/Tests/Types/AI/AIInsightStatus.test.ts +40 -0
  141. package/Tests/Types/API/HostnameAuthorityParsing.test.ts +157 -0
  142. package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +27 -0
  143. package/Tests/Types/DataSource/DataSourceLimits.test.ts +71 -0
  144. package/Tests/Types/DataSource/DataSourceType.test.ts +181 -0
  145. package/Tests/Types/DomainSubdomainValidation.test.ts +90 -0
  146. package/Tests/Types/JSONFunctions.test.ts +252 -1
  147. package/Tests/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.test.ts +61 -0
  148. package/Tests/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.test.ts +62 -0
  149. package/Tests/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.test.ts +68 -0
  150. package/Tests/Types/Monitor/SnmpMonitor/SnmpVersion.test.ts +51 -0
  151. package/Tests/UI/Components/404.test.tsx +1 -1
  152. package/Tests/UI/Components/Alert.test.tsx +1 -1
  153. package/Tests/UI/Components/Badge.test.tsx +1 -1
  154. package/Tests/UI/Components/BasicForm.test.tsx +39 -10
  155. package/Tests/UI/Components/Button.test.tsx +1 -1
  156. package/Tests/UI/Components/Card.test.tsx +1 -1
  157. package/Tests/UI/Components/Charts/AxisTickColor.test.tsx +1 -1
  158. package/Tests/UI/Components/ColorViewer.test.tsx +1 -1
  159. package/Tests/UI/Components/ComponentsModal.test.tsx +7 -1
  160. package/Tests/UI/Components/DictionaryOfStrings.test.tsx +1 -1
  161. package/Tests/UI/Components/Dropdown.test.tsx +1 -1
  162. package/Tests/UI/Components/FilePicker.test.tsx +1 -1
  163. package/Tests/UI/Components/HiddenText.test.tsx +1 -1
  164. package/Tests/UI/Components/Input.test.tsx +1 -1
  165. package/Tests/UI/Components/Loader.test.tsx +1 -1
  166. package/Tests/UI/Components/LogTimeRangePicker.test.tsx +1 -1
  167. package/Tests/UI/Components/MasterPage.test.tsx +1 -1
  168. package/Tests/UI/Components/ModalPortalDismissal.test.tsx +489 -0
  169. package/Tests/UI/Components/ModelDelete.test.tsx +214 -0
  170. package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1 -1
  171. package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +1 -1
  172. package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +1 -1
  173. package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +1 -1
  174. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1 -1
  175. package/Tests/UI/Components/NavBar.test.tsx +1 -1
  176. package/Tests/UI/Components/OperatorSelectorKeyboard.test.tsx +1 -1
  177. package/Tests/UI/Components/Pagination.test.tsx +1 -1
  178. package/Tests/UI/Components/Pill.test.tsx +1 -1
  179. package/Tests/UI/Components/Probe.test.tsx +1 -1
  180. package/Tests/UI/Components/ProgressBar.test.tsx +1 -1
  181. package/Tests/UI/Components/RadioButtons.test.tsx +1 -1
  182. package/Tests/UI/Components/SideMenuItem.test.tsx +1 -1
  183. package/Tests/UI/Components/SideOver.test.tsx +500 -6
  184. package/Tests/UI/Components/Tabs.test.tsx +1 -1
  185. package/Tests/UI/Components/TelemetrySearchBar.test.tsx +1 -1
  186. package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +1 -1
  187. package/Tests/UI/Components/TextArea.test.tsx +1 -1
  188. package/Tests/UI/Components/Toast.test.tsx +1 -1
  189. package/Tests/UI/Components/Toggle.test.tsx +1 -1
  190. package/Tests/UI/Components/TopSection.test.tsx +1 -1
  191. package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +1 -1
  192. package/Tests/UI/Rum/ReplayScrubber.test.tsx +1 -1
  193. package/Tests/UI/Rum/ReplayStage.test.tsx +1 -1
  194. package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +1 -1
  195. package/Tests/UI/Utils/LocalStorageArrayRoundTrip.test.ts +72 -0
  196. package/Tests/Utils/Dashboard/HtmlWidgetDocument.test.ts +19 -2
  197. package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +44 -0
  198. package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +288 -5
  199. package/Tests/Utils/Dashboard/VariableUrlState.test.ts +42 -0
  200. package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +27 -0
  201. package/Tests/Utils/LegacySerializedArray.test.ts +139 -0
  202. package/Tests/Utils/Monitor/MonitorDependencyRule.test.ts +190 -0
  203. package/Tests/Utils/Realtime.test.ts +78 -0
  204. package/Tests/Utils/Telemetry/SavedViewFilters.test.ts +246 -0
  205. package/Tests/__mocks__/i18next-browser-languagedetector.js +21 -0
  206. package/Types/AI/FixPullRequestCiStatus.ts +1 -1
  207. package/Types/AI/FixVerificationStatus.ts +2 -2
  208. package/Types/API/Hostname.ts +92 -4
  209. package/Types/API/URL.ts +43 -25
  210. package/Types/Billing/BalanceAdjustmentType.ts +14 -0
  211. package/Types/Billing/ProjectBalanceType.ts +13 -0
  212. package/Types/Domain.ts +26 -0
  213. package/Types/File/MimeType.ts +11 -0
  214. package/Types/JSONFunctions.ts +15 -0
  215. package/Types/Telemetry/TelemetrySavedViewState.ts +9 -1
  216. package/Types/Workflow/Components/BaseModel.ts +92 -28
  217. package/Typings/Index.d.ts +12 -0
  218. package/UI/Components/GanttChart/ChartContainer.tsx +4 -3
  219. package/UI/Components/Modal/ConfirmModal.tsx +10 -5
  220. package/UI/Components/Modal/Modal.tsx +27 -47
  221. package/UI/Components/ModelDelete/ModelDelete.tsx +23 -6
  222. package/UI/Components/SideOver/SideOver.tsx +195 -68
  223. package/UI/Utils/PageScrollLock.ts +66 -0
  224. package/Utils/Dashboard/HtmlWidgetDocument.ts +4 -2
  225. package/Utils/Dashboard/VariableInterpolation.ts +19 -1
  226. package/Utils/LegacySerializedArray.ts +60 -0
  227. package/Utils/Monitor/MonitorDependencyRule.ts +88 -0
  228. package/Utils/Telemetry/SavedViewFilters.ts +88 -0
  229. package/build/dist/Models/DatabaseModels/AIInsight.js +1 -1
  230. package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -1
  231. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js +2 -3
  232. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js.map +1 -1
  233. package/build/dist/Models/DatabaseModels/DeletedProject.js +640 -0
  234. package/build/dist/Models/DatabaseModels/DeletedProject.js.map +1 -0
  235. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  236. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  237. package/build/dist/Models/DatabaseModels/Monitor.js +106 -0
  238. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  239. package/build/dist/Models/DatabaseModels/Project.js +3 -3
  240. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  241. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  242. package/build/dist/Server/API/FileAPI.js +14 -2
  243. package/build/dist/Server/API/FileAPI.js.map +1 -1
  244. package/build/dist/Server/API/MicrosoftTeamsAPI.js +6 -1
  245. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  246. package/build/dist/Server/API/ProjectAPI.js +157 -4
  247. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  248. package/build/dist/Server/API/StatusPageAPI.js +27 -3
  249. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  250. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js +34 -0
  251. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js.map +1 -0
  252. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js +30 -0
  253. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js.map +1 -0
  254. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js +20 -0
  255. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js.map +1 -0
  256. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  257. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  258. package/build/dist/Server/Services/AIAgentService.js +17 -0
  259. package/build/dist/Server/Services/AIAgentService.js.map +1 -1
  260. package/build/dist/Server/Services/DashboardDomainService.js +55 -18
  261. package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
  262. package/build/dist/Server/Services/DatabaseService.js +1 -0
  263. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  264. package/build/dist/Server/Services/DeletedProjectService.js +124 -0
  265. package/build/dist/Server/Services/DeletedProjectService.js.map +1 -0
  266. package/build/dist/Server/Services/FileService.js +52 -0
  267. package/build/dist/Server/Services/FileService.js.map +1 -1
  268. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +10 -1
  269. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
  270. package/build/dist/Server/Services/IncidentPublicNoteService.js +10 -1
  271. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  272. package/build/dist/Server/Services/Index.js +2 -0
  273. package/build/dist/Server/Services/Index.js.map +1 -1
  274. package/build/dist/Server/Services/MonitorService.js +232 -0
  275. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  276. package/build/dist/Server/Services/ProbeService.js +17 -0
  277. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  278. package/build/dist/Server/Services/ProjectService.js +228 -6
  279. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  280. package/build/dist/Server/Services/PushNotificationService.js +56 -0
  281. package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
  282. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +10 -1
  283. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  284. package/build/dist/Server/Services/StatusPageAnnouncementService.js +54 -0
  285. package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
  286. package/build/dist/Server/Services/StatusPageDomainService.js +55 -18
  287. package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
  288. package/build/dist/Server/Services/TeamMemberService.js +97 -6
  289. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  290. package/build/dist/Server/Services/TelemetryIngestionKeyService.js +1 -0
  291. package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
  292. package/build/dist/Server/Services/UserWebhookService.js +31 -87
  293. package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
  294. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +65 -0
  295. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  296. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +23 -0
  297. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
  298. package/build/dist/Server/Types/Domain.js +37 -0
  299. package/build/dist/Server/Types/Domain.js.map +1 -1
  300. package/build/dist/Server/Types/Workflow/Components/API/Delete.js +2 -1
  301. package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
  302. package/build/dist/Server/Types/Workflow/Components/API/Get.js +2 -1
  303. package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
  304. package/build/dist/Server/Types/Workflow/Components/API/Patch.js +2 -1
  305. package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
  306. package/build/dist/Server/Types/Workflow/Components/API/Post.js +2 -1
  307. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  308. package/build/dist/Server/Types/Workflow/Components/API/Put.js +2 -1
  309. package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
  310. package/build/dist/Server/Types/Workflow/Components/API/Utils.js +35 -2
  311. package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
  312. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +15 -11
  313. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
  314. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +2 -3
  315. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
  316. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js +21 -10
  317. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js.map +1 -1
  318. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js +21 -10
  319. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js.map +1 -1
  320. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js +18 -13
  321. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js.map +1 -1
  322. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js +18 -13
  323. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js.map +1 -1
  324. package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js +43 -0
  325. package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js.map +1 -0
  326. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +116 -0
  327. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -0
  328. package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js +7 -0
  329. package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js.map +1 -1
  330. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js +24 -13
  331. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js.map +1 -1
  332. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js +27 -13
  333. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js.map +1 -1
  334. package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js +14 -6
  335. package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js.map +1 -1
  336. package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js +42 -0
  337. package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js.map +1 -0
  338. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +15 -6
  339. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
  340. package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js +10 -2
  341. package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js.map +1 -1
  342. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
  343. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +141 -0
  344. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -1
  345. package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -1
  346. package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js +1 -1
  347. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +6 -6
  348. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js.map +1 -1
  349. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +39 -5
  350. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
  351. package/build/dist/Server/Utils/DataSource/EgressGuard.js +94 -10
  352. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
  353. package/build/dist/Server/Utils/DataSource/HttpFetch.js +1 -19
  354. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  355. package/build/dist/Server/Utils/Execute.js +2 -2
  356. package/build/dist/Server/Utils/Execute.js.map +1 -1
  357. package/build/dist/Server/Utils/InlineImageAccessTokenSync.js +13 -0
  358. package/build/dist/Server/Utils/InlineImageAccessTokenSync.js.map +1 -1
  359. package/build/dist/Server/Utils/LLM/LLMService.js +43 -12
  360. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  361. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +44 -24
  362. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  363. package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js +158 -0
  364. package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js.map +1 -0
  365. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +50 -30
  366. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  367. package/build/dist/Server/Utils/Monitor/MonitorResource.js +32 -0
  368. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  369. package/build/dist/Server/Utils/Response.js +112 -5
  370. package/build/dist/Server/Utils/Response.js.map +1 -1
  371. package/build/dist/Server/Utils/SSRFProtection.js +219 -53
  372. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  373. package/build/dist/Server/Utils/StartServer.js +7 -0
  374. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  375. package/build/dist/Server/Utils/VM/VMRunner.js +73 -1
  376. package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
  377. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +445 -43
  378. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  379. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +18 -1
  380. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  381. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  382. package/build/dist/Types/AI/FixPullRequestCiStatus.js +1 -1
  383. package/build/dist/Types/AI/FixVerificationStatus.js +2 -2
  384. package/build/dist/Types/API/Hostname.js +73 -4
  385. package/build/dist/Types/API/Hostname.js.map +1 -1
  386. package/build/dist/Types/API/URL.js +42 -24
  387. package/build/dist/Types/API/URL.js.map +1 -1
  388. package/build/dist/Types/Billing/BalanceAdjustmentType.js +15 -0
  389. package/build/dist/Types/Billing/BalanceAdjustmentType.js.map +1 -0
  390. package/build/dist/Types/Billing/ProjectBalanceType.js +14 -0
  391. package/build/dist/Types/Billing/ProjectBalanceType.js.map +1 -0
  392. package/build/dist/Types/Domain.js +22 -0
  393. package/build/dist/Types/Domain.js.map +1 -1
  394. package/build/dist/Types/File/MimeType.js +11 -0
  395. package/build/dist/Types/File/MimeType.js.map +1 -1
  396. package/build/dist/Types/JSONFunctions.js +14 -0
  397. package/build/dist/Types/JSONFunctions.js.map +1 -1
  398. package/build/dist/Types/Workflow/Components/BaseModel.js +83 -28
  399. package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
  400. package/build/dist/UI/Components/GanttChart/ChartContainer.js +4 -3
  401. package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +1 -1
  402. package/build/dist/UI/Components/Modal/ConfirmModal.js +3 -1
  403. package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
  404. package/build/dist/UI/Components/Modal/Modal.js +24 -34
  405. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  406. package/build/dist/UI/Components/ModelDelete/ModelDelete.js +11 -6
  407. package/build/dist/UI/Components/ModelDelete/ModelDelete.js.map +1 -1
  408. package/build/dist/UI/Components/SideOver/SideOver.js +105 -30
  409. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  410. package/build/dist/UI/Utils/PageScrollLock.js +52 -0
  411. package/build/dist/UI/Utils/PageScrollLock.js.map +1 -0
  412. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js +4 -2
  413. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js.map +1 -1
  414. package/build/dist/Utils/Dashboard/VariableInterpolation.js +19 -1
  415. package/build/dist/Utils/Dashboard/VariableInterpolation.js.map +1 -1
  416. package/build/dist/Utils/LegacySerializedArray.js +51 -0
  417. package/build/dist/Utils/LegacySerializedArray.js.map +1 -0
  418. package/build/dist/Utils/Monitor/MonitorDependencyRule.js +47 -0
  419. package/build/dist/Utils/Monitor/MonitorDependencyRule.js.map +1 -0
  420. package/build/dist/Utils/Telemetry/SavedViewFilters.js +52 -0
  421. package/build/dist/Utils/Telemetry/SavedViewFilters.js.map +1 -0
  422. package/jest.config.json +3 -0
  423. package/package.json +1 -1
  424. package/tsconfig.json +3 -1
@@ -1,4 +1,4 @@
1
- import { JSONArray, JSONObject, ObjectType } from "../../Types/JSON";
1
+ import { JSONArray, JSONObject, JSONValue, ObjectType } from "../../Types/JSON";
2
2
  import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
3
3
  import JSONFunctions from "../../Types/JSONFunctions";
4
4
 
@@ -350,6 +350,208 @@ describe("JSONFunctions Class", () => {
350
350
  });
351
351
  });
352
352
 
353
+ /*
354
+ * serializeValue used to have no Array.isArray branch. Arrays are typeof
355
+ * "object", so anything nested deeper than one level fell through to
356
+ * serialize(), which walks with `for (const key in val)` and returned
357
+ * { "0": ..., "1": ... } in place of the array. Only the OUTERMOST array was
358
+ * safe, because serialize() special-cases an array-valued key — which is
359
+ * exactly why this went unnoticed: `{ a: [1, 2] }` looked fine.
360
+ *
361
+ * Everything stored deeper than that was silently rewritten on its way into
362
+ * a JSON column, and the object that came back out was no longer iterable.
363
+ * These tests pin the array shape at every depth.
364
+ */
365
+ describe("Nested arrays survive serialization", () => {
366
+ test("Serializes an array of tuples without collapsing the tuples into objects", () => {
367
+ const serialized: JSONObject = JSONFunctions.serialize({
368
+ filters: [
369
+ ["service", "api"],
370
+ ["status", "error"],
371
+ ],
372
+ });
373
+
374
+ expect(serialized).toEqual({
375
+ filters: [
376
+ ["service", "api"],
377
+ ["status", "error"],
378
+ ],
379
+ });
380
+ });
381
+
382
+ test("Every element of a serialized array of tuples is still an array", () => {
383
+ const serialized: JSONObject = JSONFunctions.serialize({
384
+ filters: [["service", "api"]],
385
+ });
386
+
387
+ const filters: JSONArray = serialized["filters"] as JSONArray;
388
+
389
+ expect(Array.isArray(filters)).toBe(true);
390
+ expect(Array.isArray(filters[0])).toBe(true);
391
+ });
392
+
393
+ test("A serialized tuple is still destructurable, which is how callers read it", () => {
394
+ const serialized: JSONObject = JSONFunctions.serialize({
395
+ filters: [["service", "api"]],
396
+ });
397
+
398
+ const filters: JSONArray = serialized["filters"] as JSONArray;
399
+
400
+ // This threw "(destructured parameter) is not iterable" before the fix.
401
+ const read: Array<string> = (
402
+ filters as unknown as Array<[string, string]>
403
+ ).map(([facetKey, value]: [string, string]): string => {
404
+ return `${facetKey}:${value}`;
405
+ });
406
+
407
+ expect(read).toEqual(["service:api"]);
408
+ });
409
+
410
+ test("Serializes arrays nested three and four levels deep", () => {
411
+ expect(JSONFunctions.serialize({ deep: [[[1, 2]]] })).toEqual({
412
+ deep: [[[1, 2]]],
413
+ });
414
+ expect(JSONFunctions.serialize({ deeper: [[[["x"]]]] })).toEqual({
415
+ deeper: [[[["x"]]]],
416
+ });
417
+ });
418
+
419
+ test("Serializes an array held by an object that itself sits inside an array", () => {
420
+ expect(
421
+ JSONFunctions.serialize({
422
+ queries: [{ groupBy: ["host", "region"] }, { groupBy: [] }],
423
+ }),
424
+ ).toEqual({
425
+ queries: [{ groupBy: ["host", "region"] }, { groupBy: [] }],
426
+ });
427
+ });
428
+
429
+ test("Keeps empty arrays at every depth as arrays", () => {
430
+ const serialized: JSONObject = JSONFunctions.serialize({
431
+ outer: [],
432
+ nested: [[]],
433
+ });
434
+
435
+ expect(serialized["outer"]).toEqual([]);
436
+ expect(Array.isArray(serialized["nested"])).toBe(true);
437
+ expect((serialized["nested"] as JSONArray)[0]).toEqual([]);
438
+ });
439
+
440
+ test("Keeps null and empty-string elements inside a nested array", () => {
441
+ expect(JSONFunctions.serialize({ rows: [[null, ""]] })).toEqual({
442
+ rows: [[null, ""]],
443
+ });
444
+ });
445
+
446
+ test("Still tags a Date held inside a nested array", () => {
447
+ const serialized: JSONObject = JSONFunctions.serialize({
448
+ rows: [[new Date("2023-01-01T00:00:00.000Z")]],
449
+ });
450
+
451
+ const rows: JSONArray = serialized["rows"] as JSONArray;
452
+ const inner: JSONArray = rows[0] as unknown as JSONArray;
453
+ const when: JSONObject = inner[0] as JSONObject;
454
+
455
+ expect(Array.isArray(rows)).toBe(true);
456
+ expect(Array.isArray(inner)).toBe(true);
457
+ expect(when["_type"]).toBe(ObjectType.DateTime);
458
+ });
459
+
460
+ test("Still tags a Buffer held inside a nested array rather than treating it as an array", () => {
461
+ const serialized: JSONObject = JSONFunctions.serialize({
462
+ rows: [[Buffer.from([1, 2, 3])]],
463
+ });
464
+
465
+ const inner: JSONArray = (
466
+ serialized["rows"] as JSONArray
467
+ )[0] as unknown as JSONArray;
468
+ const payload: JSONObject = inner[0] as JSONObject;
469
+
470
+ expect(Array.isArray(inner)).toBe(true);
471
+ expect(payload["_type"]).toBe(ObjectType.Buffer);
472
+ });
473
+
474
+ test("A Buffer inside a nested array rebuilds into a Buffer", () => {
475
+ const roundTripped: JSONObject = JSONFunctions.deserialize(
476
+ JSON.parse(
477
+ JSON.stringify(
478
+ JSONFunctions.serialize({ rows: [[Buffer.from([1, 2, 3])]] }),
479
+ ),
480
+ ),
481
+ );
482
+
483
+ const inner: JSONArray = (
484
+ roundTripped["rows"] as JSONArray
485
+ )[0] as unknown as JSONArray;
486
+
487
+ expect(Buffer.isBuffer(inner[0])).toBe(true);
488
+ expect(inner[0]).toEqual(Buffer.from([1, 2, 3]));
489
+ });
490
+
491
+ test("A typed array is tagged as a Buffer, never walked as an array", () => {
492
+ /*
493
+ * ArrayBuffer.isView is checked before the array branch, and it has to
494
+ * stay that way: a Uint8Array is not array-literal data and walking it
495
+ * element by element would lose the Buffer tag deserialize looks for.
496
+ */
497
+ const serialized: JSONObject = JSONFunctions.serialize({
498
+ payload: new Uint8Array([1, 2, 3]),
499
+ });
500
+
501
+ const payload: JSONObject = serialized["payload"] as JSONObject;
502
+
503
+ expect(Array.isArray(payload)).toBe(false);
504
+ expect(payload["_type"]).toBe(ObjectType.Buffer);
505
+ });
506
+
507
+ test("serializeValue returns an array when handed one directly", () => {
508
+ /*
509
+ * The path LocalStorage/SessionStorage/Cookie take — they serialize the
510
+ * caller's value itself, with no wrapper object, so a flat array reaches
511
+ * serializeValue and used to come back as { "0": ..., "1": ... }.
512
+ */
513
+ const serialized: JSONValue = JSONFunctions.serializeValue([
514
+ "service",
515
+ "api",
516
+ ]);
517
+
518
+ expect(Array.isArray(serialized)).toBe(true);
519
+ expect(serialized).toEqual(["service", "api"]);
520
+ });
521
+
522
+ test("A flat top-level array survives a serializeValue round trip", () => {
523
+ const original: JSONValue = ["time", "body", "severityText"];
524
+
525
+ const roundTripped: JSONValue = JSONFunctions.deserializeValue(
526
+ JSON.parse(
527
+ JSON.stringify(JSONFunctions.serializeValue(original)),
528
+ ) as JSONValue,
529
+ );
530
+
531
+ expect(Array.isArray(roundTripped)).toBe(true);
532
+ expect(roundTripped).toEqual(original);
533
+ });
534
+
535
+ test("serializeValue and deserializeValue agree on array-ness", () => {
536
+ const input: JSONValue = [["a", "b"], ["c"], []];
537
+
538
+ expect(JSONFunctions.serializeValue(input)).toEqual(input);
539
+ expect(JSONFunctions.deserializeValue(input)).toEqual(input);
540
+ });
541
+
542
+ test("A numeric-keyed object is still serialized as an object", () => {
543
+ // The corrupted shape itself must not be mistaken for an array.
544
+ const serialized: JSONObject = JSONFunctions.serialize({
545
+ legacy: [{ "0": "service", "1": "api" }],
546
+ });
547
+
548
+ const legacy: JSONArray = serialized["legacy"] as JSONArray;
549
+
550
+ expect(Array.isArray(legacy[0])).toBe(false);
551
+ expect(legacy[0]).toEqual({ "0": "service", "1": "api" });
552
+ });
553
+ });
554
+
353
555
  describe("serialize and deserialize round trip", () => {
354
556
  test("A plain object survives a serialize -> JSON -> deserialize round trip", () => {
355
557
  const original: JSONObject = {
@@ -363,5 +565,54 @@ describe("JSONFunctions Class", () => {
363
565
  );
364
566
  expect(roundTripped).toEqual(original);
365
567
  });
568
+
569
+ test("A saved telemetry view survives the round trip it is stored through", () => {
570
+ /*
571
+ * The exact shape TelemetrySavedViewState puts in the `query` JSON
572
+ * column of TraceSavedView / MetricSavedView.
573
+ */
574
+ const original: JSONObject = {
575
+ search: "status:error",
576
+ filters: [
577
+ ["primaryEntityId", "6512f1a0a1b2c3d4e5f60718"],
578
+ ["attributes.http.method", "GET"],
579
+ ],
580
+ timeRange: { range: "Past one hour" },
581
+ pageSize: 50,
582
+ rootOnly: false,
583
+ };
584
+
585
+ const roundTripped: JSONObject = JSONFunctions.deserialize(
586
+ JSON.parse(JSON.stringify(JSONFunctions.serialize(original))),
587
+ );
588
+
589
+ expect(roundTripped).toEqual(original);
590
+ });
591
+
592
+ test("Arrays nested at any depth survive the round trip", () => {
593
+ const original: JSONObject = {
594
+ tuples: [
595
+ ["a", "b"],
596
+ ["c", "d"],
597
+ ],
598
+ deep: [[[1, 2]]],
599
+ mixed: [{ groupBy: ["host"] }, ["x", ["y"]]],
600
+ empty: [[]],
601
+ };
602
+
603
+ const roundTripped: JSONObject = JSONFunctions.deserialize(
604
+ JSON.parse(JSON.stringify(JSONFunctions.serialize(original))),
605
+ );
606
+
607
+ expect(roundTripped).toEqual(original);
608
+ });
609
+
610
+ test("serializeArray keeps nested arrays inside each object", () => {
611
+ const input: JSONArray = [{ filters: [["a", "b"]] }];
612
+
613
+ expect(JSONFunctions.serializeArray(input)).toEqual([
614
+ { filters: [["a", "b"]] },
615
+ ]);
616
+ });
366
617
  });
367
618
  });
@@ -0,0 +1,61 @@
1
+ import SnmpAuthProtocol, {
2
+ SnmpAuthProtocolUtil,
3
+ } from "../../../../Types/Monitor/SnmpMonitor/SnmpAuthProtocol";
4
+
5
+ describe("SnmpAuthProtocolUtil.parse", () => {
6
+ test("parses each protocol from its canonical spelling", () => {
7
+ expect(SnmpAuthProtocolUtil.parse("MD5")).toBe(SnmpAuthProtocol.MD5);
8
+ expect(SnmpAuthProtocolUtil.parse("SHA")).toBe(SnmpAuthProtocol.SHA);
9
+ expect(SnmpAuthProtocolUtil.parse("SHA256")).toBe(SnmpAuthProtocol.SHA256);
10
+ expect(SnmpAuthProtocolUtil.parse("SHA512")).toBe(SnmpAuthProtocol.SHA512);
11
+ });
12
+
13
+ test("accepts the hyphenated UI labels", () => {
14
+ // "SHA-256" is the label the form shows for that option.
15
+ expect(SnmpAuthProtocolUtil.parse("SHA-256")).toBe(SnmpAuthProtocol.SHA256);
16
+ expect(SnmpAuthProtocolUtil.parse("SHA-512")).toBe(SnmpAuthProtocol.SHA512);
17
+ expect(SnmpAuthProtocolUtil.parse("SHA-1")).toBe(SnmpAuthProtocol.SHA);
18
+ });
19
+
20
+ test("treats SHA, SHA1 and SHA-1 as the same (SHA-1) algorithm", () => {
21
+ expect(SnmpAuthProtocolUtil.parse("sha")).toBe(SnmpAuthProtocol.SHA);
22
+ expect(SnmpAuthProtocolUtil.parse("sha1")).toBe(SnmpAuthProtocol.SHA);
23
+ expect(SnmpAuthProtocolUtil.parse("sha-1")).toBe(SnmpAuthProtocol.SHA);
24
+ });
25
+
26
+ test("is case-insensitive and whitespace-tolerant", () => {
27
+ expect(SnmpAuthProtocolUtil.parse(" md5 ")).toBe(SnmpAuthProtocol.MD5);
28
+ expect(SnmpAuthProtocolUtil.parse("Sha256")).toBe(SnmpAuthProtocol.SHA256);
29
+ });
30
+
31
+ test("returns undefined — never a silent default — for unknown input", () => {
32
+ /*
33
+ * Deliberately NOT defaulting to MD5: 'unset' and 'unreadable' are
34
+ * different problems and only the caller can decide the fallback.
35
+ */
36
+ expect(SnmpAuthProtocolUtil.parse("SHA-3")).toBeUndefined();
37
+ expect(SnmpAuthProtocolUtil.parse("nonsense")).toBeUndefined();
38
+ expect(SnmpAuthProtocolUtil.parse("")).toBeUndefined();
39
+ expect(SnmpAuthProtocolUtil.parse(null)).toBeUndefined();
40
+ expect(SnmpAuthProtocolUtil.parse(undefined)).toBeUndefined();
41
+ });
42
+ });
43
+
44
+ describe("SnmpAuthProtocolUtil.isUnrecognized", () => {
45
+ test("is true only when something is stored but no spelling matches", () => {
46
+ expect(SnmpAuthProtocolUtil.isUnrecognized("SHA-3")).toBe(true);
47
+ expect(SnmpAuthProtocolUtil.isUnrecognized("md-5")).toBe(true);
48
+ });
49
+
50
+ test("is false for a recognised value", () => {
51
+ expect(SnmpAuthProtocolUtil.isUnrecognized("SHA-256")).toBe(false);
52
+ expect(SnmpAuthProtocolUtil.isUnrecognized("md5")).toBe(false);
53
+ });
54
+
55
+ test("an empty or absent column is 'unset', not 'unrecognized'", () => {
56
+ expect(SnmpAuthProtocolUtil.isUnrecognized("")).toBe(false);
57
+ expect(SnmpAuthProtocolUtil.isUnrecognized(" ")).toBe(false);
58
+ expect(SnmpAuthProtocolUtil.isUnrecognized(null)).toBe(false);
59
+ expect(SnmpAuthProtocolUtil.isUnrecognized(undefined)).toBe(false);
60
+ });
61
+ });
@@ -0,0 +1,62 @@
1
+ import SnmpPrivProtocol, {
2
+ SnmpPrivProtocolUtil,
3
+ } from "../../../../Types/Monitor/SnmpMonitor/SnmpPrivProtocol";
4
+
5
+ describe("SnmpPrivProtocolUtil.parse", () => {
6
+ test("parses each cipher from its canonical spelling", () => {
7
+ expect(SnmpPrivProtocolUtil.parse("DES")).toBe(SnmpPrivProtocol.DES);
8
+ expect(SnmpPrivProtocolUtil.parse("AES")).toBe(SnmpPrivProtocol.AES);
9
+ expect(SnmpPrivProtocolUtil.parse("AES256")).toBe(SnmpPrivProtocol.AES256);
10
+ });
11
+
12
+ test("treats AES, AES128 and AES-128 as the same (AES-128) cipher", () => {
13
+ expect(SnmpPrivProtocolUtil.parse("aes")).toBe(SnmpPrivProtocol.AES);
14
+ expect(SnmpPrivProtocolUtil.parse("aes128")).toBe(SnmpPrivProtocol.AES);
15
+ expect(SnmpPrivProtocolUtil.parse("aes-128")).toBe(SnmpPrivProtocol.AES);
16
+ });
17
+
18
+ test("accepts the hyphenated UI label for AES-256", () => {
19
+ expect(SnmpPrivProtocolUtil.parse("AES-256")).toBe(SnmpPrivProtocol.AES256);
20
+ expect(SnmpPrivProtocolUtil.parse("aes256")).toBe(SnmpPrivProtocol.AES256);
21
+ });
22
+
23
+ test("is case-insensitive and whitespace-tolerant", () => {
24
+ expect(SnmpPrivProtocolUtil.parse(" des ")).toBe(SnmpPrivProtocol.DES);
25
+ expect(SnmpPrivProtocolUtil.parse("Aes-256")).toBe(SnmpPrivProtocol.AES256);
26
+ });
27
+
28
+ test("does NOT confuse the weaker AES-128 with AES-256", () => {
29
+ // Guards the exact downgrade the parser exists to prevent.
30
+ expect(SnmpPrivProtocolUtil.parse("aes")).not.toBe(SnmpPrivProtocol.AES256);
31
+ expect(SnmpPrivProtocolUtil.parse("aes-256")).not.toBe(
32
+ SnmpPrivProtocol.AES,
33
+ );
34
+ });
35
+
36
+ test("returns undefined — never a silent DES default — for unknown input", () => {
37
+ expect(SnmpPrivProtocolUtil.parse("3des")).toBeUndefined();
38
+ expect(SnmpPrivProtocolUtil.parse("rc4")).toBeUndefined();
39
+ expect(SnmpPrivProtocolUtil.parse("")).toBeUndefined();
40
+ expect(SnmpPrivProtocolUtil.parse(null)).toBeUndefined();
41
+ expect(SnmpPrivProtocolUtil.parse(undefined)).toBeUndefined();
42
+ });
43
+ });
44
+
45
+ describe("SnmpPrivProtocolUtil.isUnrecognized", () => {
46
+ test("is true only when something is stored but no spelling matches", () => {
47
+ expect(SnmpPrivProtocolUtil.isUnrecognized("3des")).toBe(true);
48
+ expect(SnmpPrivProtocolUtil.isUnrecognized("aes-512")).toBe(true);
49
+ });
50
+
51
+ test("is false for a recognised value", () => {
52
+ expect(SnmpPrivProtocolUtil.isUnrecognized("AES-256")).toBe(false);
53
+ expect(SnmpPrivProtocolUtil.isUnrecognized("des")).toBe(false);
54
+ });
55
+
56
+ test("an empty or absent column is 'unset', not 'unrecognized'", () => {
57
+ expect(SnmpPrivProtocolUtil.isUnrecognized("")).toBe(false);
58
+ expect(SnmpPrivProtocolUtil.isUnrecognized(" ")).toBe(false);
59
+ expect(SnmpPrivProtocolUtil.isUnrecognized(null)).toBe(false);
60
+ expect(SnmpPrivProtocolUtil.isUnrecognized(undefined)).toBe(false);
61
+ });
62
+ });
@@ -0,0 +1,68 @@
1
+ import SnmpSecurityLevel, {
2
+ SnmpSecurityLevelUtil,
3
+ } from "../../../../Types/Monitor/SnmpMonitor/SnmpSecurityLevel";
4
+
5
+ describe("SnmpSecurityLevelUtil.parse", () => {
6
+ test("parses each level from its value spelling", () => {
7
+ expect(SnmpSecurityLevelUtil.parse("noAuthNoPriv")).toBe(
8
+ SnmpSecurityLevel.NoAuthNoPriv,
9
+ );
10
+ expect(SnmpSecurityLevelUtil.parse("authNoPriv")).toBe(
11
+ SnmpSecurityLevel.AuthNoPriv,
12
+ );
13
+ expect(SnmpSecurityLevelUtil.parse("authPriv")).toBe(
14
+ SnmpSecurityLevel.AuthPriv,
15
+ );
16
+ });
17
+
18
+ test("collapses the key spelling onto the value spelling (case-insensitive)", () => {
19
+ /*
20
+ * The enum keys ("AuthPriv") and values ("authPriv") differ only by the
21
+ * first letter's case — exactly the drift a hand-written row produces.
22
+ */
23
+ expect(SnmpSecurityLevelUtil.parse("AuthPriv")).toBe(
24
+ SnmpSecurityLevel.AuthPriv,
25
+ );
26
+ expect(SnmpSecurityLevelUtil.parse("NOAUTHNOPRIV")).toBe(
27
+ SnmpSecurityLevel.NoAuthNoPriv,
28
+ );
29
+ });
30
+
31
+ test("is whitespace-tolerant", () => {
32
+ expect(SnmpSecurityLevelUtil.parse(" authpriv ")).toBe(
33
+ SnmpSecurityLevel.AuthPriv,
34
+ );
35
+ });
36
+
37
+ test("returns undefined rather than silently dropping to NoAuthNoPriv", () => {
38
+ /*
39
+ * The whole point: an unmatched value must not fall through to 'no
40
+ * security at all'. The caller decides, not the parser.
41
+ */
42
+ expect(SnmpSecurityLevelUtil.parse("auth")).toBeUndefined();
43
+ expect(SnmpSecurityLevelUtil.parse("priv")).toBeUndefined();
44
+ expect(SnmpSecurityLevelUtil.parse("secure")).toBeUndefined();
45
+ expect(SnmpSecurityLevelUtil.parse("")).toBeUndefined();
46
+ expect(SnmpSecurityLevelUtil.parse(null)).toBeUndefined();
47
+ expect(SnmpSecurityLevelUtil.parse(undefined)).toBeUndefined();
48
+ });
49
+ });
50
+
51
+ describe("SnmpSecurityLevelUtil.isUnrecognized", () => {
52
+ test("is true only when something is stored but no spelling matches", () => {
53
+ expect(SnmpSecurityLevelUtil.isUnrecognized("auth")).toBe(true);
54
+ expect(SnmpSecurityLevelUtil.isUnrecognized("full")).toBe(true);
55
+ });
56
+
57
+ test("is false for a recognised value in either spelling", () => {
58
+ expect(SnmpSecurityLevelUtil.isUnrecognized("authPriv")).toBe(false);
59
+ expect(SnmpSecurityLevelUtil.isUnrecognized("AuthPriv")).toBe(false);
60
+ });
61
+
62
+ test("an empty or absent column is 'unset', not 'unrecognized'", () => {
63
+ expect(SnmpSecurityLevelUtil.isUnrecognized("")).toBe(false);
64
+ expect(SnmpSecurityLevelUtil.isUnrecognized(" ")).toBe(false);
65
+ expect(SnmpSecurityLevelUtil.isUnrecognized(null)).toBe(false);
66
+ expect(SnmpSecurityLevelUtil.isUnrecognized(undefined)).toBe(false);
67
+ });
68
+ });
@@ -0,0 +1,51 @@
1
+ import SnmpVersion, {
2
+ SnmpVersionUtil,
3
+ } from "../../../../Types/Monitor/SnmpMonitor/SnmpVersion";
4
+
5
+ describe("SnmpVersionUtil.parse", () => {
6
+ test("reads the stored key spelling (V1/V3), case-insensitively", () => {
7
+ expect(SnmpVersionUtil.parse("V1")).toBe(SnmpVersion.V1);
8
+ expect(SnmpVersionUtil.parse("v1")).toBe(SnmpVersion.V1);
9
+ expect(SnmpVersionUtil.parse("V3")).toBe(SnmpVersion.V3);
10
+ expect(SnmpVersionUtil.parse("v3")).toBe(SnmpVersion.V3);
11
+ });
12
+
13
+ test("reads the probe-contract value spelling (1/3)", () => {
14
+ expect(SnmpVersionUtil.parse("1")).toBe(SnmpVersion.V1);
15
+ expect(SnmpVersionUtil.parse("3")).toBe(SnmpVersion.V3);
16
+ });
17
+
18
+ test("tolerates surrounding whitespace", () => {
19
+ expect(SnmpVersionUtil.parse(" v3 ")).toBe(SnmpVersion.V3);
20
+ expect(SnmpVersionUtil.parse("\t3\n")).toBe(SnmpVersion.V3);
21
+ });
22
+
23
+ test("defaults to V2c for the v2c spellings and anything unknown", () => {
24
+ // V2c is the default branch, so both its own spellings and junk land here.
25
+ expect(SnmpVersionUtil.parse("2c")).toBe(SnmpVersion.V2c);
26
+ expect(SnmpVersionUtil.parse("V2c")).toBe(SnmpVersion.V2c);
27
+ expect(SnmpVersionUtil.parse("banana")).toBe(SnmpVersion.V2c);
28
+ expect(SnmpVersionUtil.parse("")).toBe(SnmpVersion.V2c);
29
+ });
30
+
31
+ test("defaults to V2c for null and undefined", () => {
32
+ expect(SnmpVersionUtil.parse(null)).toBe(SnmpVersion.V2c);
33
+ expect(SnmpVersionUtil.parse(undefined)).toBe(SnmpVersion.V2c);
34
+ });
35
+ });
36
+
37
+ describe("SnmpVersionUtil.isV3", () => {
38
+ test("is true only for the v3 spellings", () => {
39
+ expect(SnmpVersionUtil.isV3("V3")).toBe(true);
40
+ expect(SnmpVersionUtil.isV3("3")).toBe(true);
41
+ expect(SnmpVersionUtil.isV3(" v3 ")).toBe(true);
42
+ });
43
+
44
+ test("is false for v1, v2c, unknown and empty input", () => {
45
+ expect(SnmpVersionUtil.isV3("V1")).toBe(false);
46
+ expect(SnmpVersionUtil.isV3("2c")).toBe(false);
47
+ expect(SnmpVersionUtil.isV3("nope")).toBe(false);
48
+ expect(SnmpVersionUtil.isV3(null)).toBe(false);
49
+ expect(SnmpVersionUtil.isV3(undefined)).toBe(false);
50
+ });
51
+ });
@@ -1,5 +1,5 @@
1
1
  import NotFound, { ComponentProps } from "../../../UI/Components/404";
2
- import "@testing-library/jest-dom/extend-expect";
2
+ import "@testing-library/jest-dom";
3
3
  import { fireEvent, render, screen } from "@testing-library/react";
4
4
  import Route from "../../../Types/API/Route";
5
5
  import Email from "../../../Types/Email";
@@ -1,5 +1,5 @@
1
1
  import Alert, { AlertType } from "../../../UI/Components/Alerts/Alert";
2
- import "@testing-library/jest-dom/extend-expect";
2
+ import "@testing-library/jest-dom";
3
3
  import { fireEvent, render, screen } from "@testing-library/react";
4
4
  import React from "react";
5
5
  import { describe, expect, jest } from "@jest/globals";
@@ -1,5 +1,5 @@
1
1
  import Badge, { BadgeType } from "../../../UI/Components/Badge/Badge";
2
- import "@testing-library/jest-dom/extend-expect";
2
+ import "@testing-library/jest-dom";
3
3
  import { render, screen } from "@testing-library/react";
4
4
  import React from "react";
5
5
  import { describe, expect, test } from "@jest/globals";
@@ -2,7 +2,7 @@ import BasicForm from "../../../UI/Components/Forms/BasicForm";
2
2
  import Fields from "../../../UI/Components/Forms/Types/Fields";
3
3
  import FormFieldSchemaType from "../../../UI/Components/Forms/Types/FormFieldSchemaType";
4
4
  import FormValues from "../../../UI/Components/Forms/Types/FormValues";
5
- import "@testing-library/jest-dom/extend-expect";
5
+ import "@testing-library/jest-dom";
6
6
  import { render, screen, waitFor } from "@testing-library/react";
7
7
  import userEvent from "@testing-library/user-event";
8
8
  import { UserEvent } from "@testing-library/user-event/dist/types/setup/setup";
@@ -11,6 +11,21 @@ import * as React from "react";
11
11
  import { describe, expect } from "@jest/globals";
12
12
  import getJestMockFunction, { MockFunction } from "../../../Tests/MockType";
13
13
 
14
+ /*
15
+ * Type without userEvent's default inter-keystroke await. Input keeps a display
16
+ * value in state, syncs it from props, and then writes it straight onto the DOM
17
+ * node -- so a keystroke that arrives before React has committed the previous
18
+ * one gets overwritten by the stale value and is destroyed rather than merely
19
+ * delayed. Nothing recovers it, and the form submits "test@sample.cm". With
20
+ * `delay: null` the whole string is dispatched inside a single act(), where
21
+ * effects flush between keys, so that window never opens. Measured on a loaded
22
+ * machine: the default pacing dropped characters in 4 runs out of 6, this in 0
23
+ * out of 8.
24
+ */
25
+ function setupUser(): UserEvent {
26
+ return userEvent.setup({ delay: null });
27
+ }
28
+
14
29
  describe("BasicForm test", () => {
15
30
  const fields: Fields<FormValues<any>> = [
16
31
  {
@@ -65,6 +80,11 @@ describe("BasicForm test", () => {
65
80
  expect(forgotPasswordText).toHaveTextContent("Forgot password?");
66
81
  });
67
82
 
83
+ /*
84
+ * The explicit timeout: typing 24 characters re-validates the whole form once
85
+ * per keystroke, which finishes well inside a second locally but has no
86
+ * headroom left against Jest's 5s default on a loaded runner.
87
+ */
68
88
  test("Should accept values and submit if valid", async () => {
69
89
  const handleSubmit: MockFunction = getJestMockFunction();
70
90
  const onSubmitSuccessful: MockFunction = getJestMockFunction();
@@ -82,7 +102,7 @@ describe("BasicForm test", () => {
82
102
  submitButtonText="Login"
83
103
  />,
84
104
  );
85
- const user: UserEvent = userEvent.setup();
105
+ const user: UserEvent = setupUser();
86
106
  await user.type(screen.getByTestId("email"), "test@sample.com");
87
107
  await user.type(screen.getByTestId("password"), "12345678");
88
108
 
@@ -101,7 +121,7 @@ describe("BasicForm test", () => {
101
121
  onSubmitSuccessful,
102
122
  );
103
123
  });
104
- });
124
+ }, 30000);
105
125
 
106
126
  test("Should display error if values are invalid", async () => {
107
127
  const handleSubmit: MockFunction = getJestMockFunction();
@@ -117,19 +137,28 @@ describe("BasicForm test", () => {
117
137
  submitButtonText="Login"
118
138
  />,
119
139
  );
120
- const user: UserEvent = userEvent.setup();
140
+ const user: UserEvent = setupUser();
121
141
  await user.type(screen.getByTestId("email"), "humed");
122
142
  await user.type(screen.getByTestId("password"), "1238");
123
143
 
124
144
  const loginButton: HTMLButtonElement = screen.getByTestId("Login");
125
145
  await user.click(loginButton);
126
146
 
127
- const errorComponent: HTMLElement[] =
128
- screen.getAllByTestId("error-message");
147
+ /*
148
+ * Both errors have to be waited for. The email error is already on screen
149
+ * -- it was raised while the user was still typing -- but the password one
150
+ * only lands once the submit-time validation has flushed, so reading the
151
+ * list straight after the click finds a single error and indexes off the
152
+ * end of it.
153
+ */
154
+ await waitFor(() => {
155
+ const errorComponent: HTMLElement[] =
156
+ screen.getAllByTestId("error-message");
129
157
 
130
- expect(errorComponent[0]?.innerHTML).toEqual("Email is not valid.");
131
- expect(errorComponent[1]?.innerHTML).toEqual(
132
- "Password cannot be less than 6 characters.",
133
- );
158
+ expect(errorComponent[0]?.innerHTML).toEqual("Email is not valid.");
159
+ expect(errorComponent[1]?.innerHTML).toEqual(
160
+ "Password cannot be less than 6 characters.",
161
+ );
162
+ });
134
163
  });
135
164
  });
@@ -4,7 +4,7 @@ import Button, {
4
4
  } from "../../../UI/Components/Button/Button";
5
5
  import ButtonType from "../../../UI/Components/Button/ButtonTypes";
6
6
  import ShortcutKey from "../../../UI/Components/ShortcutKey/ShortcutKey";
7
- import "@testing-library/jest-dom/extend-expect";
7
+ import "@testing-library/jest-dom";
8
8
  import { fireEvent, render, screen } from "@testing-library/react";
9
9
  import IconProp from "../../../Types/Icon/IconProp";
10
10
  import React from "react";
@@ -3,7 +3,7 @@ import Card, {
3
3
  CardButtonSchema,
4
4
  ComponentProps,
5
5
  } from "../../../UI/Components/Card/Card";
6
- import "@testing-library/jest-dom/extend-expect";
6
+ import "@testing-library/jest-dom";
7
7
  import { fireEvent, render, screen } from "@testing-library/react";
8
8
  import IconProp from "../../../Types/Icon/IconProp";
9
9
  import React, { ReactElement } from "react";
@@ -1,7 +1,7 @@
1
1
  import { AreaChart } from "../../../../UI/Components/Charts/ChartLibrary/AreaChart/AreaChart";
2
2
  import { BarChart } from "../../../../UI/Components/Charts/ChartLibrary/BarChart/BarChart";
3
3
  import { LineChart } from "../../../../UI/Components/Charts/ChartLibrary/LineChart/LineChart";
4
- import "@testing-library/jest-dom/extend-expect";
4
+ import "@testing-library/jest-dom";
5
5
  import { render } from "@testing-library/react";
6
6
  import React from "react";
7
7
  import { describe, expect, test } from "@jest/globals";
@@ -1,5 +1,5 @@
1
1
  import ColorViewer from "../../../UI/Components/ColorViewer/ColorViewer";
2
- import "@testing-library/jest-dom/extend-expect";
2
+ import "@testing-library/jest-dom";
3
3
  import { fireEvent, render } from "@testing-library/react";
4
4
  import Color from "../../../Types/Color";
5
5
  import * as React from "react";