@oneuptime/common 12.0.28 → 12.0.30

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 (367) hide show
  1. package/Models/DatabaseModels/DashboardDomain.ts +43 -0
  2. package/Models/DatabaseModels/Index.ts +11 -0
  3. package/Models/DatabaseModels/MonitorTemplate.ts +15 -3
  4. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +43 -0
  5. package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +662 -0
  6. package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +584 -0
  7. package/Models/DatabaseModels/StatusPageDomain.ts +43 -0
  8. package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +546 -0
  9. package/Models/DatabaseModels/UserOnCallShiftReminder.ts +231 -0
  10. package/Models/DatabaseModels/UserOnCallShiftReminderLog.ts +331 -0
  11. package/Server/API/DashboardDomainAPI.ts +74 -0
  12. package/Server/API/MicrosoftTeamsAPI.ts +81 -180
  13. package/Server/API/OnCallCalendarAPI.ts +2194 -0
  14. package/Server/API/StatusPageDomainAPI.ts +74 -0
  15. package/Server/EnvironmentConfig.ts +138 -0
  16. package/Server/Infrastructure/OnCallCalendarFeedCache.ts +1050 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.ts +43 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.ts +40 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.ts +253 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  21. package/Server/Middleware/OnCallCalendarFeedRateLimit.ts +487 -0
  22. package/Server/Middleware/ProjectAuthorization.ts +6 -1
  23. package/Server/Services/DashboardDomainService.ts +131 -0
  24. package/Server/Services/Index.ts +12 -0
  25. package/Server/Services/LogPipelineProcessorService.ts +88 -0
  26. package/Server/Services/MonitorTemplateService.ts +70 -11
  27. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +32 -0
  28. package/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.ts +260 -0
  29. package/Server/Services/OnCallDutyPolicyScheduleLayerService.ts +70 -3
  30. package/Server/Services/OnCallDutyPolicyScheduleLayerUserService.ts +138 -3
  31. package/Server/Services/OnCallDutyPolicyScheduleService.ts +1465 -134
  32. package/Server/Services/OnCallDutyPolicyUserOverrideService.ts +167 -31
  33. package/Server/Services/ProjectOnCallCalendarFeedService.ts +192 -0
  34. package/Server/Services/StatusPageDomainService.ts +163 -3
  35. package/Server/Services/StatusPagePrivateUserSessionService.ts +197 -56
  36. package/Server/Services/TeamMemberService.ts +489 -1
  37. package/Server/Services/TeamService.ts +50 -0
  38. package/Server/Services/UserNotificationSettingService.ts +44 -1
  39. package/Server/Services/UserOnCallCalendarFeedService.ts +159 -0
  40. package/Server/Services/UserOnCallShiftReminderLogService.ts +151 -0
  41. package/Server/Services/UserOnCallShiftReminderService.ts +112 -0
  42. package/Server/Types/Domain.ts +17 -0
  43. package/Server/Utils/APIKey/AccessPermission.ts +24 -0
  44. package/Server/Utils/Greenlock/Greenlock.ts +156 -58
  45. package/Server/Utils/LogPipelineProcessorValidation.ts +112 -0
  46. package/Server/Utils/OnCall/CalendarFeedToken.ts +241 -0
  47. package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1488 -0
  48. package/Server/Utils/OnCall/OnCallCalendarFeedUrls.ts +230 -0
  49. package/Server/Utils/OnCall/OnCallShiftChangeListeners.ts +227 -0
  50. package/Server/Utils/OnCall/OnCallShiftMaterializer.ts +1127 -0
  51. package/Server/Utils/OnCall/OnCallShiftReminderListener.ts +174 -0
  52. package/Server/Utils/OnCall/OnCallShiftReminderRunner.ts +2584 -0
  53. package/Server/Utils/Response.ts +134 -0
  54. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +1094 -45
  55. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +153 -17
  56. package/Server/Utils/StartServer.ts +10 -0
  57. package/Server/Utils/Telemetry/AppMetrics.ts +51 -0
  58. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +23 -11
  59. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +0 -170
  60. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.ts +158 -0
  61. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +23 -11
  62. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +35 -13
  63. package/Tests/App/Dashboard/MonitorTemplateColumnAndFacet.test.tsx +505 -0
  64. package/Tests/App/Dashboard/OnCallCalendarFeedLinks.test.tsx +229 -0
  65. package/Tests/App/Dashboard/OnCallCalendarFeedPlanGate.test.tsx +489 -0
  66. package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +149 -0
  67. package/Tests/App/Dashboard/OnCallCalendarFeedUtil.test.ts +855 -0
  68. package/Tests/App/Dashboard/OnCallPersonalCalendarFeed.test.tsx +1209 -0
  69. package/Tests/App/Dashboard/OnCallSharedCalendarFeedCard.test.tsx +1019 -0
  70. package/Tests/App/Dashboard/OnCallShiftRemindersAndUpcomingShifts.test.tsx +655 -0
  71. package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +73 -0
  72. package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +106 -0
  73. package/Tests/App/StatusPage/StatusPageLoginCodeUtil.test.ts +84 -0
  74. package/Tests/App/StatusPage/StatusPageRedirectSafety.test.ts +119 -0
  75. package/Tests/Models/MonitorTemplateMonitorNameColumn.test.ts +258 -0
  76. package/Tests/Models/OnCallCalendarFeedModels.test.ts +642 -0
  77. package/Tests/Models/OnCallDutyPolicyScheduleCalendarFeed.test.ts +288 -0
  78. package/Tests/Models/OnCallDutyPolicyScheduleShiftConfigVersion.test.ts +88 -0
  79. package/Tests/Models/UserOnCallShiftReminderModels.test.ts +368 -0
  80. package/Tests/Server/API/CustomDomainReissueSslAPI.test.ts +469 -0
  81. package/Tests/Server/API/Helpers.ts +8 -0
  82. package/Tests/Server/API/MicrosoftTeamsBotMessagesEndpoint.test.ts +729 -0
  83. package/Tests/Server/API/MicrosoftTeamsBotTestEndpoint.test.ts +26 -0
  84. package/Tests/Server/API/MicrosoftTeamsLegacyWebhookRemoval.test.ts +402 -0
  85. package/Tests/Server/API/OnCallCalendarAPI.test.ts +4461 -0
  86. package/Tests/Server/EnvironmentConfigOnCallCalendarFeed.test.ts +357 -0
  87. package/Tests/Server/Infrastructure/OnCallCalendarFeedCache.test.ts +1589 -0
  88. package/Tests/Server/Infrastructure/Postgres/AddOnCallCalendarFeedsMigration.test.ts +369 -0
  89. package/Tests/Server/Middleware/OnCallCalendarFeedRateLimit.test.ts +1365 -0
  90. package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +4 -0
  91. package/Tests/Server/Services/AddCertificateReissueRequestedAtToDomainsMigration.test.ts +287 -0
  92. package/Tests/Server/Services/CustomDomainCertificateReissue.test.ts +477 -0
  93. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +70 -0
  94. package/Tests/Server/Services/LogPipelineProcessorSaveValidation.test.ts +249 -0
  95. package/Tests/Server/Services/MonitorTemplateServiceBulkSync.test.ts +549 -0
  96. package/Tests/Server/Services/MonitorTemplateServiceNetworkDeviceSync.test.ts +16 -3
  97. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +57 -0
  98. package/Tests/Server/Services/OnCallCalendarFeedServices.test.ts +1103 -0
  99. package/Tests/Server/Services/OnCallDutyPolicyScheduleResolver.test.ts +1037 -0
  100. package/Tests/Server/Services/OnCallShiftConfigPropagation.test.ts +1270 -0
  101. package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +151 -15
  102. package/Tests/Server/Services/StatusPagePrivateUserSessionService.test.ts +587 -0
  103. package/Tests/Server/Services/TeamDeleteMemberCleanup.test.ts +156 -0
  104. package/Tests/Server/Services/TeamMemberOnCallCleanup.test.ts +755 -0
  105. package/Tests/Server/Services/UserNotificationSettingShiftReminderDefaults.test.ts +267 -0
  106. package/Tests/Server/Services/UserOnCallShiftReminderServices.test.ts +583 -0
  107. package/Tests/Server/Types/Database/Permissions/ApiKeyFileAccess.test.ts +286 -0
  108. package/Tests/Server/Types/Database/Permissions/MonitorTemplateColumnAccess.test.ts +328 -0
  109. package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +254 -0
  110. package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAndIsNull.test.ts +83 -0
  111. package/Tests/Server/Utils/AI/SRE/ConfidenceSignal.test.ts +377 -0
  112. package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +16 -1
  113. package/Tests/Server/Utils/Greenlock/CertificateRenewalSchedule.test.ts +250 -0
  114. package/Tests/Server/Utils/LogPipelineProcessorValidation.test.ts +198 -0
  115. package/Tests/Server/Utils/OnCall/CalendarFeedToken.test.ts +467 -0
  116. package/Tests/Server/Utils/OnCall/OnCallCalendarFeedRenderer.test.ts +2142 -0
  117. package/Tests/Server/Utils/OnCall/OnCallCalendarFeedUrls.test.ts +278 -0
  118. package/Tests/Server/Utils/OnCall/OnCallResolverTestHarness.ts +440 -0
  119. package/Tests/Server/Utils/OnCall/OnCallShiftChangeListeners.test.ts +314 -0
  120. package/Tests/Server/Utils/OnCall/OnCallShiftMaterializer.test.ts +1502 -0
  121. package/Tests/Server/Utils/OnCall/OnCallShiftReminderListener.test.ts +491 -0
  122. package/Tests/Server/Utils/OnCall/OnCallShiftReminderRunner.test.ts +3088 -0
  123. package/Tests/Server/Utils/OnCall/OnCallShiftReminderTestHarness.ts +910 -0
  124. package/Tests/Server/Utils/ResponseSendCalendarResponse.test.ts +561 -0
  125. package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +48 -9
  126. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsAuth.test.ts +726 -0
  127. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +74 -11
  128. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsErrorHandling.test.ts +1107 -0
  129. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +20 -3
  130. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +51 -11
  131. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +1246 -0
  132. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsRequestContract.test.ts +961 -0
  133. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsResponseParsing.test.ts +653 -0
  134. package/Tests/Server/Utils/StartServerEncryptionSecretWarning.test.ts +64 -0
  135. package/Tests/Server/Utils/Telemetry/AppMetrics.test.ts +29 -0
  136. package/Tests/Server/Utils/Workspace/MicrosoftTeamsActionAuthorization.test.ts +880 -0
  137. package/Tests/Types/API/HTTPResponse.test.ts +175 -0
  138. package/Tests/Types/API/Route.test.ts +36 -4
  139. package/Tests/Types/Calendar/ICalendar.test.ts +488 -0
  140. package/Tests/Types/Database/DatabaseProperty.test.ts +171 -0
  141. package/Tests/Types/DateLocalShortDateTimeString.test.ts +518 -0
  142. package/Tests/Types/DateLocalTimeString.test.ts +259 -0
  143. package/Tests/Types/DateUserPrefers12HourFormat.test.ts +316 -0
  144. package/Tests/Types/NotificationSetting/NotificationSettingEventType.test.ts +53 -0
  145. package/Tests/Types/OnCallDutyPolicy/CalendarFeedTestFixtures.ts +310 -0
  146. package/Tests/Types/OnCallDutyPolicy/CalendarFeedWindow.test.ts +205 -0
  147. package/Tests/Types/OnCallDutyPolicy/LayerUtilLayerMetaAndIterationCap.test.ts +458 -0
  148. package/Tests/Types/OnCallDutyPolicy/MaterializedShift.test.ts +197 -0
  149. package/Tests/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.test.ts +1986 -0
  150. package/Tests/Types/OnCallDutyPolicy/ScheduleShiftUtilGroupKey.test.ts +678 -0
  151. package/Tests/Types/OnCallDutyPolicy/ShiftSeamUtil.test.ts +417 -0
  152. package/Tests/UI/Components/LogsHistogram.test.tsx +41 -2
  153. package/Tests/UI/Components/LogsViewerEmptyStateTimeRange.test.tsx +212 -0
  154. package/Tests/UI/Components/TelemetryChartClockFormat.test.tsx +359 -0
  155. package/Tests/UI/Components/TimeRangePickerClockFormat.test.tsx +422 -0
  156. package/Tests/UI/Components/TimeRangePickerDropdown.test.tsx +146 -8
  157. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsMessagingEndpointGuidance.test.tsx +520 -0
  158. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
  159. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  160. package/Tests/UI/Utils/Navigation.test.ts +82 -0
  161. package/Tests/Utils/Array.test.ts +100 -0
  162. package/Tests/Utils/CertificateReissue.test.ts +225 -0
  163. package/Tests/Utils/Grok/Grok.test.ts +492 -0
  164. package/Tests/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.test.ts +181 -13
  165. package/Types/API/Route.ts +20 -5
  166. package/Types/Calendar/ICalendar.ts +442 -0
  167. package/Types/Date.ts +143 -13
  168. package/Types/Email/EmailTemplateType.ts +2 -0
  169. package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
  170. package/Types/OnCallDutyPolicy/CalendarFeedWindow.ts +140 -0
  171. package/Types/OnCallDutyPolicy/Layer.ts +190 -35
  172. package/Types/OnCallDutyPolicy/MaterializedShift.ts +274 -0
  173. package/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.ts +1415 -0
  174. package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +159 -4
  175. package/Types/OnCallDutyPolicy/ShiftSeamUtil.ts +106 -0
  176. package/Types/Rum/SessionReplay.ts +62 -1
  177. package/UI/Components/Date/TimeRangePickerDropdown.tsx +9 -5
  178. package/UI/Components/LogsViewer/LogsViewer.tsx +12 -7
  179. package/UI/Components/LogsViewer/components/HistogramTooltip.tsx +18 -17
  180. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +21 -28
  181. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +2 -4
  182. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +2 -4
  183. package/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.tsx +17 -16
  184. package/UI/Utils/Navigation.ts +42 -0
  185. package/Utils/Array.ts +37 -0
  186. package/Utils/CertificateReissue.ts +128 -0
  187. package/Utils/Grok/Grok.ts +461 -0
  188. package/Utils/Grok/GrokPatterns.ts +118 -0
  189. package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +58 -6
  190. package/build/dist/Models/DatabaseModels/DashboardDomain.js +44 -0
  191. package/build/dist/Models/DatabaseModels/DashboardDomain.js.map +1 -1
  192. package/build/dist/Models/DatabaseModels/Index.js +11 -0
  193. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  194. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +17 -4
  195. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  196. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +44 -0
  197. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  198. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +699 -0
  199. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -0
  200. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +620 -0
  201. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -0
  202. package/build/dist/Models/DatabaseModels/StatusPageDomain.js +44 -0
  203. package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
  204. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +585 -0
  205. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -0
  206. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminder.js +247 -0
  207. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminder.js.map +1 -0
  208. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminderLog.js +355 -0
  209. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminderLog.js.map +1 -0
  210. package/build/dist/Server/API/DashboardDomainAPI.js +43 -1
  211. package/build/dist/Server/API/DashboardDomainAPI.js.map +1 -1
  212. package/build/dist/Server/API/MicrosoftTeamsAPI.js +74 -118
  213. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  214. package/build/dist/Server/API/OnCallCalendarAPI.js +1371 -0
  215. package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -0
  216. package/build/dist/Server/API/StatusPageDomainAPI.js +43 -1
  217. package/build/dist/Server/API/StatusPageDomainAPI.js.map +1 -1
  218. package/build/dist/Server/EnvironmentConfig.js +102 -0
  219. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  220. package/build/dist/Server/Infrastructure/OnCallCalendarFeedCache.js +663 -0
  221. package/build/dist/Server/Infrastructure/OnCallCalendarFeedCache.js.map +1 -0
  222. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.js +34 -0
  223. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.js.map +1 -0
  224. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.js +28 -0
  225. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.js.map +1 -0
  226. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.js +103 -0
  227. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.js.map +1 -0
  228. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  229. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  230. package/build/dist/Server/Middleware/OnCallCalendarFeedRateLimit.js +342 -0
  231. package/build/dist/Server/Middleware/OnCallCalendarFeedRateLimit.js.map +1 -0
  232. package/build/dist/Server/Middleware/ProjectAuthorization.js +6 -1
  233. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  234. package/build/dist/Server/Services/DashboardDomainService.js +104 -0
  235. package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
  236. package/build/dist/Server/Services/Index.js +12 -0
  237. package/build/dist/Server/Services/Index.js.map +1 -1
  238. package/build/dist/Server/Services/LogPipelineProcessorService.js +65 -0
  239. package/build/dist/Server/Services/LogPipelineProcessorService.js.map +1 -1
  240. package/build/dist/Server/Services/MonitorTemplateService.js +57 -11
  241. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  242. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +20 -0
  243. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  244. package/build/dist/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.js +219 -0
  245. package/build/dist/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.js.map +1 -0
  246. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js +47 -3
  247. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js.map +1 -1
  248. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js +112 -3
  249. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js.map +1 -1
  250. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +955 -9
  251. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  252. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js +93 -6
  253. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js.map +1 -1
  254. package/build/dist/Server/Services/ProjectOnCallCalendarFeedService.js +157 -0
  255. package/build/dist/Server/Services/ProjectOnCallCalendarFeedService.js.map +1 -0
  256. package/build/dist/Server/Services/StatusPageDomainService.js +132 -3
  257. package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
  258. package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js +112 -32
  259. package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js.map +1 -1
  260. package/build/dist/Server/Services/TeamMemberService.js +396 -1
  261. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  262. package/build/dist/Server/Services/TeamService.js +43 -0
  263. package/build/dist/Server/Services/TeamService.js.map +1 -1
  264. package/build/dist/Server/Services/UserNotificationSettingService.js +26 -1
  265. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  266. package/build/dist/Server/Services/UserOnCallCalendarFeedService.js +140 -0
  267. package/build/dist/Server/Services/UserOnCallCalendarFeedService.js.map +1 -0
  268. package/build/dist/Server/Services/UserOnCallShiftReminderLogService.js +116 -0
  269. package/build/dist/Server/Services/UserOnCallShiftReminderLogService.js.map +1 -0
  270. package/build/dist/Server/Services/UserOnCallShiftReminderService.js +92 -0
  271. package/build/dist/Server/Services/UserOnCallShiftReminderService.js.map +1 -0
  272. package/build/dist/Server/Types/Domain.js +16 -0
  273. package/build/dist/Server/Types/Domain.js.map +1 -1
  274. package/build/dist/Server/Utils/APIKey/AccessPermission.js +24 -0
  275. package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
  276. package/build/dist/Server/Utils/Greenlock/Greenlock.js +110 -35
  277. package/build/dist/Server/Utils/Greenlock/Greenlock.js.map +1 -1
  278. package/build/dist/Server/Utils/LogPipelineProcessorValidation.js +77 -0
  279. package/build/dist/Server/Utils/LogPipelineProcessorValidation.js.map +1 -0
  280. package/build/dist/Server/Utils/OnCall/CalendarFeedToken.js +161 -0
  281. package/build/dist/Server/Utils/OnCall/CalendarFeedToken.js.map +1 -0
  282. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedRenderer.js +983 -0
  283. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedRenderer.js.map +1 -0
  284. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedUrls.js +155 -0
  285. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedUrls.js.map +1 -0
  286. package/build/dist/Server/Utils/OnCall/OnCallShiftChangeListeners.js +145 -0
  287. package/build/dist/Server/Utils/OnCall/OnCallShiftChangeListeners.js.map +1 -0
  288. package/build/dist/Server/Utils/OnCall/OnCallShiftMaterializer.js +752 -0
  289. package/build/dist/Server/Utils/OnCall/OnCallShiftMaterializer.js.map +1 -0
  290. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderListener.js +92 -0
  291. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderListener.js.map +1 -0
  292. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js +1786 -0
  293. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js.map +1 -0
  294. package/build/dist/Server/Utils/Response.js +97 -0
  295. package/build/dist/Server/Utils/Response.js.map +1 -1
  296. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +777 -36
  297. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
  298. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +108 -17
  299. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
  300. package/build/dist/Server/Utils/StartServer.js +9 -1
  301. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  302. package/build/dist/Server/Utils/Telemetry/AppMetrics.js +41 -0
  303. package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
  304. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +17 -6
  305. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
  306. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +0 -159
  307. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
  308. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.js +128 -0
  309. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.js.map +1 -0
  310. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +17 -6
  311. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  312. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +25 -13
  313. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  314. package/build/dist/Types/API/Route.js +16 -5
  315. package/build/dist/Types/API/Route.js.map +1 -1
  316. package/build/dist/Types/Calendar/ICalendar.js +290 -0
  317. package/build/dist/Types/Calendar/ICalendar.js.map +1 -0
  318. package/build/dist/Types/Date.js +115 -13
  319. package/build/dist/Types/Date.js.map +1 -1
  320. package/build/dist/Types/Email/EmailTemplateType.js +2 -0
  321. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  322. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
  323. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  324. package/build/dist/Types/OnCallDutyPolicy/CalendarFeedWindow.js +97 -0
  325. package/build/dist/Types/OnCallDutyPolicy/CalendarFeedWindow.js.map +1 -0
  326. package/build/dist/Types/OnCallDutyPolicy/Layer.js +113 -19
  327. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  328. package/build/dist/Types/OnCallDutyPolicy/MaterializedShift.js +134 -0
  329. package/build/dist/Types/OnCallDutyPolicy/MaterializedShift.js.map +1 -0
  330. package/build/dist/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.js +800 -0
  331. package/build/dist/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.js.map +1 -0
  332. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +97 -3
  333. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
  334. package/build/dist/Types/OnCallDutyPolicy/ShiftSeamUtil.js +77 -0
  335. package/build/dist/Types/OnCallDutyPolicy/ShiftSeamUtil.js.map +1 -0
  336. package/build/dist/Types/Rum/SessionReplay.js +38 -0
  337. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  338. package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js +9 -5
  339. package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js.map +1 -1
  340. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +12 -7
  341. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  342. package/build/dist/UI/Components/LogsViewer/components/HistogramTooltip.js +15 -14
  343. package/build/dist/UI/Components/LogsViewer/components/HistogramTooltip.js.map +1 -1
  344. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +17 -22
  345. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  346. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +2 -4
  347. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  348. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +2 -4
  349. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  350. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.js +15 -14
  351. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.js.map +1 -1
  352. package/build/dist/UI/Utils/Navigation.js +30 -0
  353. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  354. package/build/dist/Utils/Array.js +25 -0
  355. package/build/dist/Utils/Array.js.map +1 -1
  356. package/build/dist/Utils/CertificateReissue.js +97 -0
  357. package/build/dist/Utils/CertificateReissue.js.map +1 -0
  358. package/build/dist/Utils/Grok/Grok.js +324 -0
  359. package/build/dist/Utils/Grok/Grok.js.map +1 -0
  360. package/build/dist/Utils/Grok/GrokPatterns.js +112 -0
  361. package/build/dist/Utils/Grok/GrokPatterns.js.map +1 -0
  362. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +63 -3
  363. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -1
  364. package/package.json +1 -1
  365. package/UI/Utils/JsonWebToken.ts +0 -14
  366. package/build/dist/UI/Utils/JsonWebToken.js +0 -10
  367. package/build/dist/UI/Utils/JsonWebToken.js.map +0 -1
@@ -0,0 +1,442 @@
1
+ import BadDataException from "../Exception/BadDataException";
2
+
3
+ /*
4
+ * Zero-dependency RFC 5545 (iCalendar) serializer for subscription feeds.
5
+ *
6
+ * Deliberate choices, recorded here because every one of them was a
7
+ * decision, not an omission:
8
+ *
9
+ * - No METHOD. RFC 5546 (iTIP) would require ORGANIZER on a PUBLISH, and
10
+ * subscription feeds are not iTIP messages; Google, Apple and Outlook all
11
+ * treat a METHOD-less VCALENDAR as a plain calendar, which is what we are.
12
+ * - DTSTAMP = the feed input's last-modified instant, not "now". Without
13
+ * METHOD, RFC 5545 §3.8.7.2 reads DTSTAMP as the last revision, and using
14
+ * it makes an unchanged schedule serialize to a byte-identical body so ETags
15
+ * and body caches work.
16
+ * - No VTIMEZONE and no TZID. Every DTSTART/DTEND is an absolute UTC instant
17
+ * ("...Z"). The engine already resolves wall-clock rules into instants, the
18
+ * client converts to the viewer's zone, and shipping a VTIMEZONE database
19
+ * would lag IANA. Wall-clock renderings go in DESCRIPTION instead.
20
+ * - No VALARM (reminders are delivered by OneUptime's own notification path so
21
+ * they honour the user's notification settings), no RRULE (shifts are
22
+ * materialised individually so overrides and rotations never desynchronise),
23
+ * no CLASS (Outlook maps CLASS:PRIVATE to Private sensitivity and Google to
24
+ * private visibility, which blanks a shared team calendar for everyone but
25
+ * its owner), no ORGANIZER/ATTENDEE.
26
+ * - Both REFRESH-INTERVAL;VALUE=DURATION (RFC 7986) and X-PUBLISHED-TTL are
27
+ * emitted from the same duration: classic Outlook honours X-PUBLISHED-TTL
28
+ * when "Update Limit" is on and never refreshes a feed without it.
29
+ * - Property order inside VCALENDAR and VEVENT is fixed so equal inputs give
30
+ * equal bytes.
31
+ *
32
+ * Wire format: CRLF line breaks, content lines folded at 75 octets on UTF-8
33
+ * character boundaries (RFC 5545 §3.1), TEXT values escaped per §3.3.11.
34
+ */
35
+
36
+ export const ICALENDAR_LINE_BREAK: string = "\r\n";
37
+
38
+ // RFC 5545 §3.1: lines SHOULD NOT be longer than 75 octets, excluding CRLF.
39
+ export const ICALENDAR_MAX_LINE_OCTETS: number = 75;
40
+
41
+ export const ICALENDAR_VERSION: string = "2.0";
42
+
43
+ export enum ICalendarEventStatus {
44
+ Confirmed = "CONFIRMED",
45
+ Tentative = "TENTATIVE",
46
+ Cancelled = "CANCELLED",
47
+ }
48
+
49
+ export enum ICalendarTransparency {
50
+ Transparent = "TRANSPARENT",
51
+ Opaque = "OPAQUE",
52
+ }
53
+
54
+ export interface ICalendarCalendar {
55
+ // PRODID, e.g. "-//OneUptime//On-Call Calendar Feed//EN".
56
+ productId: string;
57
+ // NAME (RFC 7986) — the full calendar name.
58
+ name?: string | undefined;
59
+ // X-WR-CALNAME — what most clients actually display; defaults to `name`.
60
+ displayName?: string | undefined;
61
+ // X-WR-CALDESC.
62
+ description?: string | undefined;
63
+ // X-WR-TIMEZONE, an IANA zone name.
64
+ timezone?: string | undefined;
65
+ // ISO 8601 duration ("PT1H") for REFRESH-INTERVAL and X-PUBLISHED-TTL.
66
+ refreshInterval?: string | undefined;
67
+ // Calendar-level LAST-MODIFIED (RFC 7986).
68
+ lastModified?: Date | undefined;
69
+ }
70
+
71
+ export interface ICalendarEvent {
72
+ uid: string;
73
+ dtStamp: Date;
74
+ start: Date;
75
+ // Exclusive, like DTEND.
76
+ end: Date;
77
+ summary: string;
78
+ description?: string | undefined;
79
+ location?: string | undefined;
80
+ url?: string | undefined;
81
+ lastModified?: Date | undefined;
82
+ // Non-negative integer; bumps tell clients the event was revised.
83
+ sequence?: number | undefined;
84
+ status?: ICalendarEventStatus | undefined;
85
+ transparency?: ICalendarTransparency | undefined;
86
+ categories?: Array<string> | undefined;
87
+ }
88
+
89
+ export interface ICalendarDocument {
90
+ calendar: ICalendarCalendar;
91
+ events: Array<ICalendarEvent>;
92
+ }
93
+
94
+ const ISO_8601_DURATION_REGEX: RegExp =
95
+ /^P(?:\d+W|(?:\d+D)?(?:T(?:\d+H)?(?:\d+M)?(?:\d+S)?)?)$/;
96
+
97
+ // RFC 5545 §3.2: a parameter value holding any of these must be quoted.
98
+ const RESERVED_PARAMETER_CHARACTERS: RegExp = /[;:,]/;
99
+
100
+ export default class ICalendar {
101
+ public static serialize(document: ICalendarDocument): string {
102
+ const lines: Array<string> = [];
103
+
104
+ lines.push("BEGIN:VCALENDAR");
105
+ lines.push(`VERSION:${ICALENDAR_VERSION}`);
106
+ lines.push(ICalendar.contentLine("PRODID", document.calendar.productId));
107
+ lines.push("CALSCALE:GREGORIAN");
108
+
109
+ const calendar: ICalendarCalendar = document.calendar;
110
+
111
+ if (calendar.name !== undefined && calendar.name !== "") {
112
+ lines.push(ICalendar.textLine("NAME", calendar.name));
113
+ }
114
+
115
+ const displayName: string | undefined =
116
+ calendar.displayName !== undefined && calendar.displayName !== ""
117
+ ? calendar.displayName
118
+ : calendar.name;
119
+
120
+ if (displayName !== undefined && displayName !== "") {
121
+ lines.push(ICalendar.textLine("X-WR-CALNAME", displayName));
122
+ }
123
+
124
+ if (calendar.description !== undefined && calendar.description !== "") {
125
+ lines.push(ICalendar.textLine("X-WR-CALDESC", calendar.description));
126
+ }
127
+
128
+ if (calendar.timezone !== undefined && calendar.timezone !== "") {
129
+ lines.push(ICalendar.textLine("X-WR-TIMEZONE", calendar.timezone));
130
+ }
131
+
132
+ if (calendar.refreshInterval !== undefined) {
133
+ const duration: string = ICalendar.validateDuration(
134
+ calendar.refreshInterval,
135
+ );
136
+ lines.push(
137
+ ICalendar.contentLine("REFRESH-INTERVAL", duration, {
138
+ VALUE: "DURATION",
139
+ }),
140
+ );
141
+ lines.push(ICalendar.contentLine("X-PUBLISHED-TTL", duration));
142
+ }
143
+
144
+ if (calendar.lastModified !== undefined) {
145
+ lines.push(
146
+ ICalendar.contentLine(
147
+ "LAST-MODIFIED",
148
+ ICalendar.formatUtcDateTime(calendar.lastModified),
149
+ ),
150
+ );
151
+ }
152
+
153
+ for (const event of document.events) {
154
+ lines.push(...ICalendar.serializeEvent(event));
155
+ }
156
+
157
+ lines.push("END:VCALENDAR");
158
+
159
+ return (
160
+ lines
161
+ .map((line: string) => {
162
+ return ICalendar.foldLine(line);
163
+ })
164
+ .join(ICALENDAR_LINE_BREAK) + ICALENDAR_LINE_BREAK
165
+ );
166
+ }
167
+
168
+ /*
169
+ * The unfolded content lines of one VEVENT, in the fixed order. Exposed so
170
+ * tests and callers can inspect a single event without a whole document.
171
+ */
172
+ public static serializeEvent(event: ICalendarEvent): Array<string> {
173
+ if (!event.uid || event.uid.trim() === "") {
174
+ throw new BadDataException("iCalendar event UID must not be empty");
175
+ }
176
+
177
+ if (event.end.getTime() <= event.start.getTime()) {
178
+ throw new BadDataException(
179
+ `iCalendar event ${event.uid} must end after it starts`,
180
+ );
181
+ }
182
+
183
+ const lines: Array<string> = [];
184
+
185
+ lines.push("BEGIN:VEVENT");
186
+ lines.push(ICalendar.textLine("UID", event.uid));
187
+ lines.push(
188
+ ICalendar.contentLine(
189
+ "DTSTAMP",
190
+ ICalendar.formatUtcDateTime(event.dtStamp),
191
+ ),
192
+ );
193
+
194
+ if (event.lastModified !== undefined) {
195
+ lines.push(
196
+ ICalendar.contentLine(
197
+ "LAST-MODIFIED",
198
+ ICalendar.formatUtcDateTime(event.lastModified),
199
+ ),
200
+ );
201
+ }
202
+
203
+ if (event.sequence !== undefined) {
204
+ lines.push(
205
+ ICalendar.contentLine(
206
+ "SEQUENCE",
207
+ String(ICalendar.validateSequence(event.sequence)),
208
+ ),
209
+ );
210
+ }
211
+
212
+ lines.push(
213
+ ICalendar.contentLine(
214
+ "DTSTART",
215
+ ICalendar.formatUtcDateTime(event.start),
216
+ ),
217
+ );
218
+ lines.push(
219
+ ICalendar.contentLine("DTEND", ICalendar.formatUtcDateTime(event.end)),
220
+ );
221
+ lines.push(ICalendar.textLine("SUMMARY", event.summary));
222
+
223
+ if (event.description !== undefined && event.description !== "") {
224
+ lines.push(ICalendar.textLine("DESCRIPTION", event.description));
225
+ }
226
+
227
+ if (event.location !== undefined && event.location !== "") {
228
+ lines.push(ICalendar.textLine("LOCATION", event.location));
229
+ }
230
+
231
+ if (event.url !== undefined && event.url !== "") {
232
+ // URI value type: not TEXT-escaped, but never allowed to break the line.
233
+ lines.push(
234
+ ICalendar.contentLine("URL", ICalendar.stripLineBreaks(event.url)),
235
+ );
236
+ }
237
+
238
+ if (event.status !== undefined) {
239
+ lines.push(ICalendar.contentLine("STATUS", event.status));
240
+ }
241
+
242
+ if (event.transparency !== undefined) {
243
+ lines.push(ICalendar.contentLine("TRANSP", event.transparency));
244
+ }
245
+
246
+ if (event.categories !== undefined && event.categories.length > 0) {
247
+ lines.push(
248
+ ICalendar.contentLine(
249
+ "CATEGORIES",
250
+ event.categories
251
+ .map((category: string) => {
252
+ return ICalendar.escapeText(category);
253
+ })
254
+ .join(","),
255
+ ),
256
+ );
257
+ }
258
+
259
+ lines.push("END:VEVENT");
260
+
261
+ return lines;
262
+ }
263
+
264
+ /*
265
+ * RFC 5545 §3.3.11 TEXT escaping: backslash, semicolon and comma are
266
+ * escaped; a newline becomes the two characters "\n"; carriage returns and
267
+ * other control characters (which TEXT may not contain) are dropped.
268
+ */
269
+ public static escapeText(text: string): string {
270
+ let result: string = "";
271
+
272
+ for (const char of text) {
273
+ if (char === "\\") {
274
+ result += "\\\\";
275
+ } else if (char === ";") {
276
+ result += "\\;";
277
+ } else if (char === ",") {
278
+ result += "\\,";
279
+ } else if (char === "\n") {
280
+ result += "\\n";
281
+ } else if (char === "\t") {
282
+ result += char;
283
+ } else if (ICalendar.isControlCharacter(char)) {
284
+ continue;
285
+ } else {
286
+ result += char;
287
+ }
288
+ }
289
+
290
+ return result;
291
+ }
292
+
293
+ // "YYYYMMDDTHHMMSSZ" — RFC 5545 §3.3.5 form #2, UTC.
294
+ public static formatUtcDateTime(date: Date): string {
295
+ if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
296
+ throw new BadDataException("iCalendar date is not a valid Date");
297
+ }
298
+
299
+ const pad: (value: number) => string = (value: number): string => {
300
+ return value < 10 ? `0${value}` : String(value);
301
+ };
302
+
303
+ return (
304
+ `${date.getUTCFullYear()}${pad(date.getUTCMonth() + 1)}${pad(date.getUTCDate())}` +
305
+ `T${pad(date.getUTCHours())}${pad(date.getUTCMinutes())}${pad(date.getUTCSeconds())}Z`
306
+ );
307
+ }
308
+
309
+ /*
310
+ * Fold one logical content line at 75 octets (RFC 5545 §3.1). The
311
+ * continuation lines start with a single space that counts toward their
312
+ * own 75-octet budget. Never splits inside a UTF-8 multi-byte sequence:
313
+ * the walk is per code point and each code point's octet length is known.
314
+ */
315
+ public static foldLine(line: string): string {
316
+ if (ICalendar.getUtf8OctetLength(line) <= ICALENDAR_MAX_LINE_OCTETS) {
317
+ return line;
318
+ }
319
+
320
+ const pieces: Array<string> = [];
321
+ let current: string = "";
322
+ let currentOctets: number = 0;
323
+ // The first physical line has the full budget; continuations lose one to the leading space.
324
+ let budget: number = ICALENDAR_MAX_LINE_OCTETS;
325
+
326
+ for (const char of line) {
327
+ const octets: number = ICalendar.getUtf8OctetLength(char);
328
+
329
+ if (currentOctets + octets > budget) {
330
+ pieces.push(current);
331
+ current = "";
332
+ currentOctets = 0;
333
+ budget = ICALENDAR_MAX_LINE_OCTETS - 1;
334
+ }
335
+
336
+ current += char;
337
+ currentOctets += octets;
338
+ }
339
+
340
+ if (current !== "") {
341
+ pieces.push(current);
342
+ }
343
+
344
+ return pieces.join(`${ICALENDAR_LINE_BREAK} `);
345
+ }
346
+
347
+ // Reverse of foldLine, for tests and readers: joins continuation lines.
348
+ public static unfold(body: string): string {
349
+ return body.replace(/\r\n[ \t]/g, "");
350
+ }
351
+
352
+ public static getUtf8OctetLength(text: string): number {
353
+ let octets: number = 0;
354
+
355
+ for (const char of text) {
356
+ const codePoint: number = char.codePointAt(0) ?? 0;
357
+
358
+ if (codePoint < 0x80) {
359
+ octets += 1;
360
+ } else if (codePoint < 0x800) {
361
+ octets += 2;
362
+ } else if (codePoint < 0x10000) {
363
+ octets += 3;
364
+ } else {
365
+ octets += 4;
366
+ }
367
+ }
368
+
369
+ return octets;
370
+ }
371
+
372
+ /*
373
+ * "NAME;PARAM=value:value" with the value used verbatim (callers escape
374
+ * TEXT values themselves or use textLine). Parameter values that contain
375
+ * characters RFC 5545 §3.2 reserves are quoted; double quotes inside them
376
+ * are dropped because there is no way to escape them.
377
+ */
378
+ public static contentLine(
379
+ name: string,
380
+ value: string,
381
+ parameters?: Record<string, string> | undefined,
382
+ ): string {
383
+ let line: string = name.toUpperCase();
384
+
385
+ if (parameters) {
386
+ for (const parameterName of Object.keys(parameters)) {
387
+ const rawValue: string = (parameters[parameterName] ?? "").replace(
388
+ /"/g,
389
+ "",
390
+ );
391
+ const needsQuotes: boolean =
392
+ RESERVED_PARAMETER_CHARACTERS.test(rawValue);
393
+ line += `;${parameterName.toUpperCase()}=${
394
+ needsQuotes ? `"${rawValue}"` : rawValue
395
+ }`;
396
+ }
397
+ }
398
+
399
+ return `${line}:${ICalendar.stripLineBreaks(value)}`;
400
+ }
401
+
402
+ // A TEXT property: the value is escaped per §3.3.11.
403
+ public static textLine(name: string, value: string): string {
404
+ return ICalendar.contentLine(name, ICalendar.escapeText(value));
405
+ }
406
+
407
+ private static validateDuration(duration: string): string {
408
+ const trimmed: string = duration.trim().toUpperCase();
409
+
410
+ if (
411
+ !ISO_8601_DURATION_REGEX.test(trimmed) ||
412
+ trimmed === "P" ||
413
+ trimmed === "PT"
414
+ ) {
415
+ throw new BadDataException(
416
+ `iCalendar refresh interval must be an ISO 8601 duration, got "${duration}"`,
417
+ );
418
+ }
419
+
420
+ return trimmed;
421
+ }
422
+
423
+ private static validateSequence(sequence: number): number {
424
+ if (!Number.isInteger(sequence) || sequence < 0) {
425
+ throw new BadDataException(
426
+ `iCalendar SEQUENCE must be a non-negative integer, got ${sequence}`,
427
+ );
428
+ }
429
+
430
+ return sequence;
431
+ }
432
+
433
+ private static isControlCharacter(char: string): boolean {
434
+ const codePoint: number = char.codePointAt(0) ?? 0;
435
+ return codePoint < 0x20 || codePoint === 0x7f;
436
+ }
437
+
438
+ // Line breaks can never appear inside a content line, whatever the value type.
439
+ private static stripLineBreaks(value: string): string {
440
+ return value.replace(/[\r\n]+/g, "");
441
+ }
442
+ }
package/Types/Date.ts CHANGED
@@ -194,32 +194,48 @@ export default class OneUptimeDate {
194
194
  return this.getLocalShortMonthName(date);
195
195
  }
196
196
 
197
+ /**
198
+ * The wall clock `date` reads at in the current timezone - "14:30", or
199
+ * "2:30 PM" when the caller asks for a 12-hour clock.
200
+ *
201
+ * `use12HourFormat` is opt-in rather than defaulted to
202
+ * `getUserPrefers12HourFormat()`: the chart x-axes in
203
+ * UI/Components/Charts/Utils/XAxis.ts label ticks with this and are laid out
204
+ * for the fixed width of a 24-hour reading, so they must keep the clock they
205
+ * were built against. Surfaces that show a person a timestamp - histogram
206
+ * ticks and tooltips, span rows - pass
207
+ * `use12HourFormat: OneUptimeDate.getUserPrefers12HourFormat()` explicitly.
208
+ */
197
209
  public static getLocalTimeString(
198
210
  date: Date | string,
199
211
  options?: {
200
212
  includeMinutes?: boolean;
201
213
  includeSeconds?: boolean;
214
+ use12HourFormat?: boolean | undefined;
202
215
  },
203
216
  ): string {
204
217
  date = this.fromString(date);
205
218
 
206
219
  const includeMinutes: boolean = options?.includeMinutes ?? true;
207
220
  const includeSeconds: boolean = options?.includeSeconds ?? false;
208
- const localDate: moment.Moment = this.inCurrentTimezone(date);
209
- const hours: string = this.padDatePart(localDate.hours());
221
+ const use12HourFormat: boolean = options?.use12HourFormat ?? false;
210
222
 
211
- if (!includeMinutes) {
212
- return hours;
213
- }
223
+ // "HH" and "h" are the zero-padded 24-hour and the bare 12-hour readings.
224
+ let timeFormat: string = use12HourFormat ? "h" : "HH";
214
225
 
215
- const minutes: string = this.padDatePart(localDate.minutes());
226
+ if (includeMinutes) {
227
+ timeFormat += ":mm";
228
+
229
+ if (includeSeconds) {
230
+ timeFormat += ":ss";
231
+ }
232
+ }
216
233
 
217
- if (!includeSeconds) {
218
- return `${hours}:${minutes}`;
234
+ if (use12HourFormat) {
235
+ timeFormat += " A";
219
236
  }
220
237
 
221
- const seconds: string = this.padDatePart(localDate.seconds());
222
- return `${hours}:${minutes}:${seconds}`;
238
+ return this.inCurrentTimezone(date).format(timeFormat);
223
239
  }
224
240
 
225
241
  public static getDateAsLocalDayMonthString(date: Date | string): string {
@@ -237,6 +253,41 @@ export default class OneUptimeDate {
237
253
  return `${this.getDateAsLocalDayMonthString(date)}, ${this.getLocalTimeString(date, { includeMinutes: false })}:00`;
238
254
  }
239
255
 
256
+ /**
257
+ * A compact "Mar 1, 14:30" (or "Mar 1, 2:30 PM") label for one instant, used
258
+ * where a whole window has to fit on a button - the time range picker above
259
+ * the metrics, traces and logs explorers, chiefly.
260
+ *
261
+ * Both halves follow the user's machine: the wall clock is resolved in the
262
+ * configured timezone (falling back to the one the browser reports), and the
263
+ * 12- vs 24-hour choice follows the operating system's clock preference
264
+ * unless a caller overrides it.
265
+ */
266
+ public static getDateAsLocalShortDateTimeString(
267
+ date: Date | string,
268
+ options?: {
269
+ use12HourFormat?: boolean | undefined;
270
+ includeSeconds?: boolean | undefined;
271
+ },
272
+ ): string {
273
+ date = this.fromString(date);
274
+
275
+ const use12HourFormat: boolean =
276
+ options?.use12HourFormat ?? this.getUserPrefers12HourFormat();
277
+
278
+ let timeFormat: string = use12HourFormat ? "h:mm" : "HH:mm";
279
+
280
+ if (options?.includeSeconds) {
281
+ timeFormat += ":ss";
282
+ }
283
+
284
+ if (use12HourFormat) {
285
+ timeFormat += " A";
286
+ }
287
+
288
+ return this.inCurrentTimezone(date).format(`MMM D, ${timeFormat}`);
289
+ }
290
+
240
291
  public static getDateAsLocalMonthYearString(date: Date | string): string {
241
292
  date = this.fromString(date);
242
293
 
@@ -857,6 +908,25 @@ export default class OneUptimeDate {
857
908
  return moment(date1).isSame(date2, "day");
858
909
  }
859
910
 
911
+ /**
912
+ * Whether the two instants fall on the same calendar day *in the current
913
+ * timezone*, which is the question a UI is asking when it decides whether a
914
+ * timestamp needs its date spelled out or a bare clock reading will do.
915
+ *
916
+ * `areOnTheSameDay` above answers it in the zone the process happens to run
917
+ * in. Near midnight those two zones disagree, so asking the wrong one drops
918
+ * the date from yesterday's buckets and adds it to today's.
919
+ */
920
+ public static areOnTheSameLocalDay(
921
+ date1: Date | string,
922
+ date2: Date | string,
923
+ ): boolean {
924
+ return this.inCurrentTimezone(date1).isSame(
925
+ this.inCurrentTimezone(date2),
926
+ "day",
927
+ );
928
+ }
929
+
860
930
  public static areOnTheSameMonth(date1: Date, date2: Date): boolean {
861
931
  date1 = this.fromString(date1);
862
932
  date2 = this.fromString(date2);
@@ -1465,15 +1535,75 @@ export default class OneUptimeDate {
1465
1535
  return this.getDateAsFormattedString(new Date(), options);
1466
1536
  }
1467
1537
 
1538
+ /**
1539
+ * Whether the machine this is running on writes the time of day on a 12-hour
1540
+ * clock, read from the browser's resolved default locale - which browsers
1541
+ * derive from the operating system's language and region, so changing those
1542
+ * changes this. An explicit -u-hc- override on the locale is honoured too.
1543
+ *
1544
+ * Note what this cannot see: the standalone "24-Hour Time" switch macOS and
1545
+ * Windows offer separately from the region. Safari and recent Firefox fold
1546
+ * that into the locale they resolve; Chromium does not. A user who wants a
1547
+ * clock that ignores their region would need an explicit preference stored
1548
+ * alongside the timezone in User Settings - there is none today.
1549
+ *
1550
+ * Asked of Intl rather than inferred from a formatted string. The string
1551
+ * probe below only recognises the Latin "AM"/"PM", so it misread every
1552
+ * 12-hour locale that marks the day period some other way - ko-KR writes
1553
+ * the equivalent of "PM" in Hangul, ar-EG in Arabic script - and served
1554
+ * those users a 24-hour clock against their own convention.
1555
+ */
1468
1556
  public static getUserPrefers12HourFormat(): boolean {
1469
1557
  if (typeof window === "undefined") {
1470
1558
  // Server-side: default to 12-hour format for user-friendly display
1471
1559
  return true;
1472
1560
  }
1473
1561
 
1474
- // Client-side: detect user's preferred time format from browser locale
1475
- const testDate: Date = new Date();
1476
- const timeString: string = testDate.toLocaleTimeString();
1562
+ /*
1563
+ * `hour12` is only reported when the format actually asks for an hour, so
1564
+ * the probe has to request one.
1565
+ */
1566
+ try {
1567
+ /*
1568
+ * Typed structurally rather than as Intl.ResolvedDateTimeFormatOptions:
1569
+ * `hourCycle` only appears on that interface from the ES2021 lib, and
1570
+ * this file has to compile against the older one too.
1571
+ */
1572
+ const resolvedOptions: {
1573
+ hour12?: boolean | undefined;
1574
+ hourCycle?: string | undefined;
1575
+ } = new Intl.DateTimeFormat(undefined, {
1576
+ hour: "numeric",
1577
+ }).resolvedOptions();
1578
+
1579
+ if (typeof resolvedOptions.hour12 === "boolean") {
1580
+ return resolvedOptions.hour12;
1581
+ }
1582
+
1583
+ /*
1584
+ * Older engines report the cycle but not the boolean. h11/h12 are the
1585
+ * two 12-hour cycles; h23/h24 are the 24-hour ones.
1586
+ */
1587
+ if (resolvedOptions.hourCycle) {
1588
+ return (
1589
+ resolvedOptions.hourCycle === "h11" ||
1590
+ resolvedOptions.hourCycle === "h12"
1591
+ );
1592
+ }
1593
+ } catch {
1594
+ /*
1595
+ * A missing or broken Intl must not take every timestamp in the UI down
1596
+ * with it - fall through to the string probe below.
1597
+ */
1598
+ }
1599
+
1600
+ /*
1601
+ * Last resort: read a formatted time and look for a day-period marker.
1602
+ * This only recognises the Latin "AM"/"PM" - which is exactly why it is the
1603
+ * fallback and not the primary check, since locales like ko-KR and ar-EG
1604
+ * are 12-hour but mark the day period with characters this cannot see.
1605
+ */
1606
+ const timeString: string = new Date().toLocaleTimeString();
1477
1607
  return (
1478
1608
  timeString.toLowerCase().includes("am") ||
1479
1609
  timeString.toLowerCase().includes("pm")
@@ -87,6 +87,8 @@ enum EmailTemplateType {
87
87
  UserCurrentlyOnOnCallRoster = "UserCurrentlyOnOnCallRoster.hbs",
88
88
  UserNextOnOnCallRoster = "UserNextOnOnCallRoster.hbs",
89
89
  UserNoLongerActiveOnOnCallRoster = "UserNoLongerActiveOnOnCallRoster.hbs",
90
+ UserOnCallShiftReminder = "UserOnCallShiftReminder.hbs",
91
+ UserOnCallShiftReassigned = "UserOnCallShiftReassigned.hbs",
90
92
 
91
93
  ProjectSubscriptionOverdue = "ProjectSubscriptionOverdue.hbs",
92
94
  Invoice = "Invoice.hbs",
@@ -68,6 +68,10 @@ enum NotificationSettingEventType {
68
68
  SEND_WHEN_USER_IS_ADDED_TO_ON_CALL_POLICY = "When user is added to on-call policy",
69
69
  SEND_WHEN_USER_IS_REMOVED_FROM_ON_CALL_POLICY = "When user is removed from on-call policy",
70
70
  SEND_WHEN_USER_IS_NO_LONGER_ACTIVE_ON_ON_CALL_ROSTER = "When user is no longer active on on-call roster",
71
+
72
+ // On Call Shift Reminders (see UserOnCallShiftReminder)
73
+ SEND_BEFORE_USER_ON_CALL_SHIFT_STARTS = "Before user's on-call shift starts",
74
+ SEND_WHEN_USER_ON_CALL_SHIFT_IS_REASSIGNED = "User's upcoming on-call shift is reassigned",
71
75
  }
72
76
 
73
77
  export default NotificationSettingEventType;