@oneuptime/common 11.7.1 → 11.7.2

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 (237) hide show
  1. package/Models/DatabaseModels/DashboardDomain.ts +1 -0
  2. package/Models/DatabaseModels/Incident.ts +2 -0
  3. package/Models/DatabaseModels/IncidentEpisode.ts +1 -0
  4. package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +1 -0
  5. package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
  6. package/Models/DatabaseModels/IncidentPublicNote.ts +1 -0
  7. package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
  8. package/Models/DatabaseModels/Monitor.ts +1 -0
  9. package/Models/DatabaseModels/MonitorStatusTimeline.ts +1 -0
  10. package/Models/DatabaseModels/NetworkSite.ts +1 -0
  11. package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +1 -0
  12. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +1 -0
  13. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +2 -0
  14. package/Models/DatabaseModels/Probe.ts +13 -13
  15. package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
  16. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +1 -0
  17. package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
  18. package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +1 -0
  19. package/Models/DatabaseModels/StatusPage.ts +1 -0
  20. package/Models/DatabaseModels/StatusPageAnnouncement.ts +1 -0
  21. package/Models/DatabaseModels/StatusPageDomain.ts +1 -0
  22. package/Models/DatabaseModels/WorkspaceNotificationSummary.ts +1 -0
  23. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +11 -0
  24. package/Server/API/BaseAPI.ts +17 -1
  25. package/Server/API/CommonAPI.ts +32 -0
  26. package/Server/API/MicrosoftTeamsAPI.ts +99 -2
  27. package/Server/API/ProbeAPI.ts +2 -0
  28. package/Server/API/SlackAPI.ts +62 -0
  29. package/Server/API/StatusPageAPI.ts +157 -192
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.ts +89 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.ts +61 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.ts +280 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  34. package/Server/Services/DatabaseService.ts +11 -3
  35. package/Server/Services/MonitorGroupService.ts +145 -0
  36. package/Server/Services/MonitorService.ts +231 -30
  37. package/Server/Services/ProbeService.ts +319 -16
  38. package/Server/Services/StatusPageService.ts +72 -42
  39. package/Server/Services/WorkspaceNotificationRuleService.ts +232 -2
  40. package/Server/Utils/Database/PostgresErrorTranslator.ts +131 -0
  41. package/Server/Utils/Monitor/MonitorResource.ts +88 -35
  42. package/Server/Utils/Monitor/MonitorStatusTimeline.ts +21 -1
  43. package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +158 -0
  44. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +706 -6
  45. package/Tests/Models/DatabaseModels/ProbeColumnAccessControl.test.ts +103 -0
  46. package/Tests/Server/API/BaseAPIUpdateNoOp.test.ts +135 -0
  47. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +317 -0
  48. package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +228 -0
  49. package/Tests/Server/API/ProbeAPI.test.ts +6 -0
  50. package/Tests/Server/API/ZZVerifyChatsAuth.test.ts +167 -0
  51. package/Tests/Server/Services/AddHotQueryIndexesMigration.test.ts +255 -0
  52. package/Tests/Server/Services/AddHotQueryIndexesSecondPassMigration.test.ts +258 -0
  53. package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +1 -1
  54. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +121 -0
  55. package/Tests/Server/Services/HeartbeatWriteFastPathSafety.test.ts +200 -0
  56. package/Tests/Server/Services/HookFreeWriteSafetySecondPass.test.ts +181 -0
  57. package/Tests/Server/Services/MonitorGroupServiceBatchedStatuses.test.ts +513 -0
  58. package/Tests/Server/Services/MonitorResourceProbeAgreementReuse.test.ts +492 -0
  59. package/Tests/Server/Services/MonitorServiceProbeSelection.test.ts +401 -0
  60. package/Tests/Server/Services/MonitorStatusTimelineFastPath.test.ts +453 -0
  61. package/Tests/Server/Services/ProbeAuthKeyCacheAndHeartbeat.test.ts +679 -0
  62. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +3 -3
  63. package/Tests/Server/Services/StatusPageDomainResolutionCache.test.ts +245 -0
  64. package/Tests/Server/Services/StatusPageOverviewTimelineWindow.test.ts +283 -0
  65. package/Tests/Server/Services/StatusPageServiceMcp.test.ts +17 -1
  66. package/Tests/Server/Services/StatusPageServiceMonitorGroupBatching.test.ts +331 -0
  67. package/Tests/Server/Services/UserOnCallLogClaimNotificationRule.test.ts +12 -12
  68. package/Tests/Server/Services/WorkspaceNotificationRuleChats.test.ts +1390 -0
  69. package/Tests/Server/Utils/AI/Insights/InsightFixRouting.test.ts +4 -4
  70. package/Tests/Server/Utils/AI/Insights/InsightScanner.test.ts +2 -2
  71. package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +1 -3
  72. package/Tests/Server/Utils/AI/Insights/InsightStoreHardening.test.ts +1 -3
  73. package/Tests/Server/Utils/AI/Insights/InsightTriage.test.ts +1 -1
  74. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +5 -5
  75. package/Tests/Server/Utils/Alert/AlertPrivacyFilter.test.ts +187 -0
  76. package/Tests/Server/Utils/AlertEpisode/AlertEpisodePrivacyFilter.test.ts +170 -0
  77. package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +125 -0
  78. package/Tests/Server/Utils/Incident/IncidentPrivacyFilter.test.ts +264 -0
  79. package/Tests/Server/Utils/IncidentEpisode/IncidentEpisodePrivacyFilter.test.ts +175 -0
  80. package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +181 -0
  81. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +1 -1
  82. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +2 -2
  83. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +341 -0
  84. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +2175 -0
  85. package/Tests/Server/Utils/Workspace/SlackChannelsList.test.ts +585 -0
  86. package/Tests/Types/Billing/MeteredPlan.test.ts +46 -0
  87. package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +219 -1
  88. package/Tests/UI/Components/BulkUpdateForm.test.tsx +174 -0
  89. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +315 -0
  90. package/Tests/UI/Components/ModelDetailSelect.test.tsx +229 -0
  91. package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1258 -0
  92. package/Tests/UI/Components/ModelTableExportFromColumns.test.ts +153 -0
  93. package/Tests/UI/Components/MonacoLoader.test.ts +67 -0
  94. package/Tests/UI/Components/MonacoRuntime.test.ts +121 -0
  95. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +212 -3
  96. package/Tests/UI/Utils/Project.test.ts +809 -0
  97. package/Tests/UI/Utils/TableColumnsToCsv.test.ts +360 -0
  98. package/Tests/Utils/Alerts/AlertMetricType.test.ts +143 -0
  99. package/Tests/Utils/Dashboard/VariableUrlState.test.ts +219 -0
  100. package/Tests/Utils/Incident/IncidentMetricType.test.ts +174 -0
  101. package/Tests/Utils/Monitor/MonitorProbeSelectionUtil.test.ts +145 -0
  102. package/Tests/Utils/StatusPage/ResourceUptime.test.ts +263 -0
  103. package/Types/Workspace/NotificationRules/BaseNotificationRule.ts +4 -0
  104. package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +25 -10
  105. package/Types/Workspace/WorkspaceMessagePayload.ts +1 -0
  106. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +63 -8
  107. package/UI/Components/CodeEditor/CodeEditor.tsx +3 -0
  108. package/UI/Components/CodeEditor/MonacoLoader.ts +36 -0
  109. package/UI/Components/Forms/ModelForm.tsx +41 -18
  110. package/UI/Components/ModelDetail/CardModelDetail.tsx +23 -1
  111. package/UI/Components/ModelDetail/ModelDetail.tsx +46 -1
  112. package/UI/Components/ModelTable/BaseModelTable.tsx +300 -30
  113. package/UI/Components/ModelTable/Column.ts +12 -0
  114. package/UI/Components/ModelTable/ExportFromColumns.ts +57 -0
  115. package/UI/Components/Navbar/NavBar.tsx +66 -1
  116. package/UI/Components/Table/Table.tsx +52 -13
  117. package/UI/Components/Table/Types/Column.ts +18 -0
  118. package/UI/Utils/Project.ts +214 -18
  119. package/UI/Utils/TableColumnsToCsv.ts +86 -6
  120. package/UI/esbuild-config.js +34 -0
  121. package/Utils/Monitor/MonitorProbeSelectionUtil.ts +72 -0
  122. package/build/dist/Models/DatabaseModels/DashboardDomain.js +1 -0
  123. package/build/dist/Models/DatabaseModels/DashboardDomain.js.map +1 -1
  124. package/build/dist/Models/DatabaseModels/Incident.js +2 -0
  125. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  126. package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1 -0
  127. package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
  128. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +1 -0
  129. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
  130. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
  131. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
  132. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +1 -0
  133. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  134. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
  135. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
  136. package/build/dist/Models/DatabaseModels/Monitor.js +1 -0
  137. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  138. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +1 -0
  139. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
  140. package/build/dist/Models/DatabaseModels/NetworkSite.js +1 -0
  141. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
  142. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +1 -0
  143. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -1
  144. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +1 -0
  145. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  146. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +2 -0
  147. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  148. package/build/dist/Models/DatabaseModels/Probe.js +13 -13
  149. package/build/dist/Models/DatabaseModels/Probe.js.map +1 -1
  150. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -0
  151. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  152. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +1 -0
  153. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  154. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
  155. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
  156. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +1 -0
  157. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
  158. package/build/dist/Models/DatabaseModels/StatusPage.js +1 -0
  159. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  160. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +1 -0
  161. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  162. package/build/dist/Models/DatabaseModels/StatusPageDomain.js +1 -0
  163. package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
  164. package/build/dist/Models/DatabaseModels/WorkspaceNotificationSummary.js +1 -0
  165. package/build/dist/Models/DatabaseModels/WorkspaceNotificationSummary.js.map +1 -1
  166. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  167. package/build/dist/Server/API/BaseAPI.js +12 -1
  168. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  169. package/build/dist/Server/API/CommonAPI.js +21 -0
  170. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  171. package/build/dist/Server/API/MicrosoftTeamsAPI.js +72 -2
  172. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  173. package/build/dist/Server/API/ProbeAPI.js +2 -0
  174. package/build/dist/Server/API/ProbeAPI.js.map +1 -1
  175. package/build/dist/Server/API/SlackAPI.js +44 -0
  176. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  177. package/build/dist/Server/API/StatusPageAPI.js +98 -152
  178. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  179. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.js +36 -0
  180. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.js.map +1 -0
  181. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.js +26 -0
  182. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.js.map +1 -0
  183. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.js +254 -0
  184. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.js.map +1 -0
  185. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  186. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  187. package/build/dist/Server/Services/DatabaseService.js +10 -2
  188. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  189. package/build/dist/Server/Services/MonitorGroupService.js +118 -0
  190. package/build/dist/Server/Services/MonitorGroupService.js.map +1 -1
  191. package/build/dist/Server/Services/MonitorService.js +198 -24
  192. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  193. package/build/dist/Server/Services/ProbeService.js +238 -9
  194. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  195. package/build/dist/Server/Services/StatusPageService.js +46 -39
  196. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  197. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +178 -3
  198. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  199. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +80 -0
  200. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -0
  201. package/build/dist/Server/Utils/Monitor/MonitorResource.js +67 -29
  202. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  203. package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js +31 -14
  204. package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js.map +1 -1
  205. package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +117 -0
  206. package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -0
  207. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +549 -7
  208. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  209. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +17 -7
  210. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
  211. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +37 -11
  212. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  213. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +2 -0
  214. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  215. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +34 -0
  216. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +1 -0
  217. package/build/dist/UI/Components/Forms/ModelForm.js +37 -17
  218. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  219. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +22 -1
  220. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
  221. package/build/dist/UI/Components/ModelDetail/ModelDetail.js +31 -1
  222. package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
  223. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +234 -21
  224. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  225. package/build/dist/UI/Components/ModelTable/ExportFromColumns.js +30 -0
  226. package/build/dist/UI/Components/ModelTable/ExportFromColumns.js.map +1 -0
  227. package/build/dist/UI/Components/Navbar/NavBar.js +39 -1
  228. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  229. package/build/dist/UI/Components/Table/Table.js +31 -11
  230. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  231. package/build/dist/UI/Utils/Project.js +161 -15
  232. package/build/dist/UI/Utils/Project.js.map +1 -1
  233. package/build/dist/UI/Utils/TableColumnsToCsv.js +67 -6
  234. package/build/dist/UI/Utils/TableColumnsToCsv.js.map +1 -1
  235. package/build/dist/Utils/Monitor/MonitorProbeSelectionUtil.js +52 -0
  236. package/build/dist/Utils/Monitor/MonitorProbeSelectionUtil.js.map +1 -0
  237. package/package.json +4 -3
@@ -17,7 +17,6 @@ import IncidentPublicNoteService from "../Services/IncidentPublicNoteService";
17
17
  import IncidentService from "../Services/IncidentService";
18
18
  import IncidentStateService from "../Services/IncidentStateService";
19
19
  import IncidentStateTimelineService from "../Services/IncidentStateTimelineService";
20
- import MonitorGroupResourceService from "../Services/MonitorGroupResourceService";
21
20
  import MonitorGroupService from "../Services/MonitorGroupService";
22
21
  import MonitorStatusService from "../Services/MonitorStatusService";
23
22
  import ScheduledMaintenancePublicNoteService from "../Services/ScheduledMaintenancePublicNoteService";
@@ -97,38 +96,16 @@ import StatusPageSubscriberNotificationEventType from "../../Types/StatusPage/St
97
96
  import StatusPageSubscriberNotificationMethod from "../../Types/StatusPage/StatusPageSubscriberNotificationMethod";
98
97
  import StatusPageSubscriberNotificationTemplateService, { Service as StatusPageSubscriberNotificationTemplateServiceClass, } from "../Services/StatusPageSubscriberNotificationTemplateService";
99
98
  const resolveStatusPageIdOrThrow = async (statusPageIdOrDomain) => {
100
- if (!statusPageIdOrDomain) {
101
- throw new NotFoundException("Status Page not found");
102
- }
103
- if (statusPageIdOrDomain.includes(".")) {
104
- const statusPageDomain = await StatusPageDomainService.findOneBy({
105
- query: {
106
- fullDomain: statusPageIdOrDomain,
107
- domain: {
108
- isVerified: true,
109
- },
110
- },
111
- select: {
112
- statusPageId: true,
113
- },
114
- props: {
115
- isRoot: true,
116
- },
117
- });
118
- if (!statusPageDomain || !statusPageDomain.statusPageId) {
119
- throw new NotFoundException("Status Page not found");
120
- }
121
- return statusPageDomain.statusPageId;
122
- }
123
- try {
124
- ObjectID.validateUUID(statusPageIdOrDomain);
125
- return new ObjectID(statusPageIdOrDomain);
126
- }
127
- catch (err) {
128
- logger.error(`Error converting statusPageIdOrDomain to ObjectID: ${statusPageIdOrDomain}`);
129
- logger.error(err);
99
+ /*
100
+ * Delegates to the service resolver so every endpoint shares its
101
+ * custom-domain -> statusPageId cache (one Postgres lookup per domain per
102
+ * TTL instead of one per request).
103
+ */
104
+ const statusPageId = await StatusPageService.resolveStatusPageIdOrNull(statusPageIdOrDomain);
105
+ if (!statusPageId) {
130
106
  throw new NotFoundException("Status Page not found");
131
107
  }
108
+ return statusPageId;
132
109
  };
133
110
  export default class StatusPageAPI extends BaseAPI {
134
111
  constructor() {
@@ -138,38 +115,10 @@ export default class StatusPageAPI extends BaseAPI {
138
115
  this.router.get(`${(_a = new this.entityType().getCrudApiPath()) === null || _a === void 0 ? void 0 : _a.toString()}/seo/:statusPageIdOrDomain`, UserMiddleware.getUserMiddleware, async (req, res) => {
139
116
  var _a;
140
117
  const statusPageIdOrDomain = req.params["statusPageIdOrDomain"];
141
- let statusPageId = null;
142
- if (statusPageIdOrDomain && statusPageIdOrDomain.includes(".")) {
143
- // then this is a domain and not the status page id. We need to get the status page id from the domain.
144
- const statusPageDomain = await StatusPageDomainService.findOneBy({
145
- query: {
146
- fullDomain: statusPageIdOrDomain,
147
- domain: {
148
- isVerified: true,
149
- },
150
- },
151
- select: {
152
- statusPageId: true,
153
- },
154
- props: {
155
- isRoot: true,
156
- },
157
- });
158
- if (!statusPageDomain || !statusPageDomain.statusPageId) {
159
- return Response.sendErrorResponse(req, res, new NotFoundException("Status Page not found"));
160
- }
161
- statusPageId = statusPageDomain.statusPageId;
162
- }
163
- else {
164
- // then this is a status page id. We need to get the status page id from the id.
165
- try {
166
- statusPageId = new ObjectID(statusPageIdOrDomain);
167
- }
168
- catch (err) {
169
- logger.error(`Error converting statusPageIdOrDomain to ObjectID: ${statusPageIdOrDomain}`, getLogAttributesFromRequest(req));
170
- logger.error(err, getLogAttributesFromRequest(req));
171
- return Response.sendErrorResponse(req, res, new NotFoundException("Status Page not found"));
172
- }
118
+ // Shares the service resolver's custom-domain -> statusPageId cache.
119
+ const statusPageId = await StatusPageService.resolveStatusPageIdOrNull(statusPageIdOrDomain);
120
+ if (!statusPageId) {
121
+ return Response.sendErrorResponse(req, res, new NotFoundException("Status Page not found"));
173
122
  }
174
123
  const statusPage = await StatusPageService.findOneBy({
175
124
  query: {
@@ -1045,31 +994,15 @@ export default class StatusPageAPI extends BaseAPI {
1045
994
  statusPageId: statusPageId,
1046
995
  req: req,
1047
996
  });
1048
- // First fetch the status page to get the configured uptime history days
1049
- const statusPageForDays = await StatusPageService.findOneBy({
1050
- query: {
1051
- _id: statusPageId.toString(),
1052
- },
1053
- select: {
1054
- showUptimeHistoryInDays: true,
1055
- },
1056
- props: {
1057
- isRoot: true,
1058
- },
1059
- });
1060
- let uptimeHistoryDays = (statusPageForDays === null || statusPageForDays === void 0 ? void 0 : statusPageForDays.showUptimeHistoryInDays) || 90;
1061
- if (uptimeHistoryDays > 90) {
1062
- uptimeHistoryDays = 90;
1063
- }
1064
- if (uptimeHistoryDays < 1) {
1065
- uptimeHistoryDays = 1;
1066
- }
1067
- const startDate = OneUptimeDate.getSomeDaysAgo(uptimeHistoryDays);
1068
- const endDate = OneUptimeDate.getCurrentDate();
1069
- const { monitorStatuses, monitorGroupCurrentStatuses, statusPageResources, statusPage, monitorsOnStatusPage, monitorStatusTimelines, statusPageGroups, monitorsInGroup, } = await this.getStatusPageResourcesAndTimelines({
997
+ /*
998
+ * The timeline window comes from the status page's configured
999
+ * showUptimeHistoryInDays. getStatusPageResourcesAndTimelines
1000
+ * fetches the status page row anyway, so let it compute the window
1001
+ * (clamped to 1..90 days, ending now) instead of issuing a separate
1002
+ * StatusPage query here just to read that one column.
1003
+ */
1004
+ const { monitorStatuses, monitorGroupCurrentStatuses, statusPageResources, statusPage, monitorsOnStatusPage, monitorStatusTimelines, statusPageGroups, monitorsInGroup, startDateForMonitorTimeline: startDate, endDateForMonitorTimeline: endDate, } = await this.getStatusPageResourcesAndTimelines({
1070
1005
  statusPageId: statusPageId,
1071
- startDateForMonitorTimeline: startDate,
1072
- endDateForMonitorTimeline: endDate,
1073
1006
  });
1074
1007
  // check if status page has active incident.
1075
1008
  let activeIncidents = [];
@@ -1200,8 +1133,38 @@ export default class StatusPageAPI extends BaseAPI {
1200
1133
  let activeEpisodesJson = [];
1201
1134
  let episodePublicNotes = [];
1202
1135
  let episodeStateTimelines = [];
1136
+ /*
1137
+ * Cheap guard before the expensive part: the block below scans every
1138
+ * incident ever attached to this page's monitors (a many-to-many
1139
+ * join, up to LIMIT_PER_PROJECT rows) just to discover episode
1140
+ * membership — on every overview view, even though most pages have
1141
+ * zero active episodes most of the time. One indexed COUNT of the
1142
+ * project's unresolved, visible episodes lets us skip all of it in
1143
+ * the common case. Behavior-preserving: the final activeEpisodes
1144
+ * query applies exactly these three constraints, so count == 0
1145
+ * implies the block's outputs stay empty.
1146
+ */
1147
+ let unresolvedIncidentStateIds = [];
1148
+ let hasActiveEpisodes = false;
1203
1149
  if (statusPage.showEpisodesOnStatusPage &&
1204
1150
  monitorsOnStatusPage.length > 0) {
1151
+ const unresolvedIncidentStates = await IncidentStateService.getUnresolvedIncidentStates(statusPage.projectId, { isRoot: true });
1152
+ unresolvedIncidentStateIds = unresolvedIncidentStates.map((state) => {
1153
+ return state.id;
1154
+ });
1155
+ const activeEpisodeCount = await IncidentEpisodeService.countBy({
1156
+ query: {
1157
+ projectId: statusPage.projectId,
1158
+ isVisibleOnStatusPage: true,
1159
+ currentIncidentStateId: QueryHelper.any(unresolvedIncidentStateIds),
1160
+ },
1161
+ props: {
1162
+ isRoot: true,
1163
+ },
1164
+ });
1165
+ hasActiveEpisodes = activeEpisodeCount.toNumber() > 0;
1166
+ }
1167
+ if (hasActiveEpisodes) {
1205
1168
  // First, get incidents that have monitors on status page
1206
1169
  const incidentsForEpisodes = await IncidentService.findBy({
1207
1170
  query: {
@@ -1249,10 +1212,7 @@ export default class StatusPageAPI extends BaseAPI {
1249
1212
  }
1250
1213
  // Fetch active (unresolved) episodes
1251
1214
  if (episodeIdsFromMembers.size > 0) {
1252
- const unresolvedIncidentStates = await IncidentStateService.getUnresolvedIncidentStates(statusPage.projectId, { isRoot: true });
1253
- const unresolvedIncidentStateIds = unresolvedIncidentStates.map((state) => {
1254
- return state.id;
1255
- });
1215
+ // unresolvedIncidentStateIds was fetched by the guard above.
1256
1216
  let selectEpisodes = {
1257
1217
  createdAt: true,
1258
1218
  declaredAt: true,
@@ -2074,28 +2034,11 @@ export default class StatusPageAPI extends BaseAPI {
2074
2034
  .filter((id) => {
2075
2035
  return Boolean(id); // remove nulls
2076
2036
  });
2037
+ // Batched: one query for all monitor groups instead of one per group.
2038
+ const monitorIdsByGroupId = await MonitorGroupService.getMonitorIdsInMonitorGroups(monitorGroupIds);
2077
2039
  for (const monitorGroupId of monitorGroupIds) {
2078
2040
  // get monitors in the group.
2079
- const groupResources = await MonitorGroupResourceService.findBy({
2080
- query: {
2081
- monitorGroupId: monitorGroupId,
2082
- },
2083
- select: {
2084
- monitorId: true,
2085
- },
2086
- props: {
2087
- isRoot: true,
2088
- },
2089
- limit: LIMIT_PER_PROJECT,
2090
- skip: 0,
2091
- });
2092
- const monitorsInGroupIds = groupResources
2093
- .map((resource) => {
2094
- return resource.monitorId;
2095
- })
2096
- .filter((id) => {
2097
- return Boolean(id); // remove nulls
2098
- });
2041
+ const monitorsInGroupIds = monitorIdsByGroupId[monitorGroupId.toString()] || [];
2099
2042
  for (const monitorId of monitorsInGroupIds) {
2100
2043
  if (!monitorsOnStatusPage.find((item) => {
2101
2044
  return item.toString() === monitorId.toString();
@@ -2245,28 +2188,11 @@ export default class StatusPageAPI extends BaseAPI {
2245
2188
  .filter((id) => {
2246
2189
  return Boolean(id); // remove nulls
2247
2190
  });
2191
+ // Batched: one query for all monitor groups instead of one per group.
2192
+ const monitorIdsByGroupId = await MonitorGroupService.getMonitorIdsInMonitorGroups(monitorGroupIds);
2248
2193
  for (const monitorGroupId of monitorGroupIds) {
2249
2194
  // get monitors in the group.
2250
- const groupResources = await MonitorGroupResourceService.findBy({
2251
- query: {
2252
- monitorGroupId: monitorGroupId,
2253
- },
2254
- select: {
2255
- monitorId: true,
2256
- },
2257
- props: {
2258
- isRoot: true,
2259
- },
2260
- limit: LIMIT_PER_PROJECT,
2261
- skip: 0,
2262
- });
2263
- const monitorsInGroupIds = groupResources
2264
- .map((resource) => {
2265
- return resource.monitorId;
2266
- })
2267
- .filter((id) => {
2268
- return Boolean(id); // remove nulls
2269
- });
2195
+ const monitorsInGroupIds = monitorIdsByGroupId[monitorGroupId.toString()] || [];
2270
2196
  for (const monitorId of monitorsInGroupIds) {
2271
2197
  if (!monitorsOnStatusPage.find((item) => {
2272
2198
  return item.toString() === monitorId.toString();
@@ -2811,6 +2737,8 @@ export default class StatusPageAPI extends BaseAPI {
2811
2737
  });
2812
2738
  const { monitorsOnStatusPage, monitorsInGroup } = await StatusPageService.getMonitorIdsOnStatusPage({
2813
2739
  statusPageId: statusPageId,
2740
+ // reuse the resources fetched above instead of re-querying them
2741
+ statusPageResources: statusPageResources,
2814
2742
  });
2815
2743
  const today = OneUptimeDate.getCurrentDate();
2816
2744
  const historyDays = OneUptimeDate.getSomeDaysAgo(statusPage.showIncidentHistoryInDays || 14);
@@ -3024,6 +2952,8 @@ export default class StatusPageAPI extends BaseAPI {
3024
2952
  });
3025
2953
  const { monitorsOnStatusPage, monitorsInGroup } = await StatusPageService.getMonitorIdsOnStatusPage({
3026
2954
  statusPageId: statusPageId,
2955
+ // reuse the resources fetched above instead of re-querying them
2956
+ statusPageResources: statusPageResources,
3027
2957
  });
3028
2958
  const today = OneUptimeDate.getCurrentDate();
3029
2959
  const historyDays = OneUptimeDate.getSomeDaysAgo(statusPage.showEpisodeHistoryInDays || 14);
@@ -3399,6 +3329,20 @@ export default class StatusPageAPI extends BaseAPI {
3399
3329
  if (!statusPage) {
3400
3330
  throw new BadDataException("Status Page not found");
3401
3331
  }
3332
+ let startDateForMonitorTimeline = data.startDateForMonitorTimeline;
3333
+ let endDateForMonitorTimeline = data.endDateForMonitorTimeline;
3334
+ if (!startDateForMonitorTimeline || !endDateForMonitorTimeline) {
3335
+ let uptimeHistoryDays = statusPage.showUptimeHistoryInDays || 90;
3336
+ if (uptimeHistoryDays > 90) {
3337
+ uptimeHistoryDays = 90;
3338
+ }
3339
+ if (uptimeHistoryDays < 1) {
3340
+ uptimeHistoryDays = 1;
3341
+ }
3342
+ startDateForMonitorTimeline =
3343
+ OneUptimeDate.getSomeDaysAgo(uptimeHistoryDays);
3344
+ endDateForMonitorTimeline = OneUptimeDate.getCurrentDate();
3345
+ }
3402
3346
  //get monitor statuses
3403
3347
  const monitorStatuses = await MonitorStatusService.findBy({
3404
3348
  query: {
@@ -3514,28 +3458,28 @@ export default class StatusPageAPI extends BaseAPI {
3514
3458
  .filter((id) => {
3515
3459
  return Boolean(id); // remove nulls
3516
3460
  });
3461
+ /*
3462
+ * Batched: this loop used to issue 4 queries per monitor group per page
3463
+ * view (3 inside MonitorGroupService.getCurrentStatus + one duplicate
3464
+ * group-resource fetch), on the hottest public endpoint in the product.
3465
+ * One shared fetch + the already-loaded `monitorStatuses` now serve every
3466
+ * group.
3467
+ */
3468
+ const monitorGroupResourcesByGroupId = await MonitorGroupService.getMonitorGroupResourcesByGroupIds(monitorGroupIds);
3469
+ const monitorGroupStatuses = await MonitorGroupService.getCurrentStatusesForMonitorGroups({
3470
+ monitorGroupIds: monitorGroupIds,
3471
+ monitorStatuses: monitorStatuses,
3472
+ monitorGroupResources: monitorGroupResourcesByGroupId,
3473
+ });
3517
3474
  for (const monitorGroupId of monitorGroupIds) {
3518
3475
  // get current status of monitors in the group.
3519
- const currentStatus = await MonitorGroupService.getCurrentStatus(monitorGroupId, {
3520
- isRoot: true,
3521
- });
3522
- monitorGroupCurrentStatuses[monitorGroupId.toString()] =
3523
- currentStatus.id;
3476
+ const currentStatus = monitorGroupStatuses[monitorGroupId.toString()];
3477
+ if (currentStatus) {
3478
+ monitorGroupCurrentStatuses[monitorGroupId.toString()] =
3479
+ currentStatus.id;
3480
+ }
3524
3481
  // get monitors in the group.
3525
- const groupResources = await MonitorGroupResourceService.findBy({
3526
- query: {
3527
- monitorGroupId: monitorGroupId,
3528
- },
3529
- select: {
3530
- monitorId: true,
3531
- },
3532
- props: {
3533
- isRoot: true,
3534
- },
3535
- limit: LIMIT_PER_PROJECT,
3536
- skip: 0,
3537
- });
3538
- const monitorsInGroupIds = groupResources
3482
+ const monitorsInGroupIds = (monitorGroupResourcesByGroupId[monitorGroupId.toString()] || [])
3539
3483
  .map((resource) => {
3540
3484
  return resource.monitorId;
3541
3485
  })
@@ -3568,8 +3512,8 @@ export default class StatusPageAPI extends BaseAPI {
3568
3512
  }
3569
3513
  const monitorStatusTimelines = await StatusPageService.getMonitorStatusTimelineForStatusPage({
3570
3514
  monitorIds: monitorsOnStatusPageForTimeline,
3571
- startDate: data.startDateForMonitorTimeline,
3572
- endDate: data.endDateForMonitorTimeline,
3515
+ startDate: startDateForMonitorTimeline,
3516
+ endDate: endDateForMonitorTimeline,
3573
3517
  });
3574
3518
  // return everything.
3575
3519
  return {
@@ -3581,6 +3525,8 @@ export default class StatusPageAPI extends BaseAPI {
3581
3525
  statusPage,
3582
3526
  monitorsOnStatusPage,
3583
3527
  monitorsInGroup,
3528
+ startDateForMonitorTimeline,
3529
+ endDateForMonitorTimeline,
3584
3530
  };
3585
3531
  }
3586
3532
  async getStatusPageAnnouncementAttachment(req, res) {