@oneuptime/common 12.0.13 → 12.0.14
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.
- package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
- package/Models/DatabaseModels/UserCall.ts +94 -3
- package/Models/DatabaseModels/UserEmail.ts +94 -3
- package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
- package/Models/DatabaseModels/UserPush.ts +37 -0
- package/Models/DatabaseModels/UserSMS.ts +94 -3
- package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
- package/Server/API/BaseAPI.ts +79 -14
- package/Server/API/UserCallAPI.ts +53 -45
- package/Server/API/UserEmailAPI.ts +53 -44
- package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
- package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
- package/Server/API/UserPushAPI.ts +126 -2
- package/Server/API/UserSmsAPI.ts +53 -44
- package/Server/API/UserWhatsAppAPI.ts +53 -50
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
- package/Server/Services/AnalyticsDatabaseService.ts +169 -0
- package/Server/Services/DatabaseService.ts +101 -0
- package/Server/Services/LogAggregationService.ts +5 -0
- package/Server/Services/PushNotificationService.ts +127 -12
- package/Server/Services/TeamMemberService.ts +53 -13
- package/Server/Services/UserCallService.ts +55 -24
- package/Server/Services/UserEmailService.ts +83 -17
- package/Server/Services/UserIncomingCallNumberService.ts +49 -85
- package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
- package/Server/Services/UserNotificationRuleService.ts +26 -0
- package/Server/Services/UserPushService.ts +89 -0
- package/Server/Services/UserSmsService.ts +50 -17
- package/Server/Services/UserWhatsAppService.ts +48 -15
- package/Server/Types/Database/QueryHelper.ts +30 -0
- package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
- package/Server/Utils/ChannelVerification.ts +510 -0
- package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +13 -16
- package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
- package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
- package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
- package/Server/Utils/TotpAuth.ts +137 -9
- package/Server/Utils/UserRegistrationToken.ts +182 -0
- package/Server/Utils/VerificationCode.ts +134 -0
- package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
- package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
- package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +28 -0
- package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
- package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
- package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
- package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
- package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
- package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
- package/Tests/Server/API/UserSmsApi.test.ts +107 -14
- package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
- package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +315 -0
- package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
- package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +10 -62
- package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
- package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
- package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
- package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
- package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
- package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
- package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
- package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
- package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
- package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
- package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
- package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
- package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
- package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
- package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
- package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
- package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
- package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
- package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
- package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
- package/Tests/Server/Utils/Browser.test.ts +162 -0
- package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
- package/Tests/Server/Utils/Express.test.ts +371 -0
- package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
- package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
- package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
- package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
- package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
- package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
- package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
- package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
- package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
- package/Tests/Types/Call/CallRequest.test.ts +189 -0
- package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
- package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
- package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
- package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
- package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
- package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
- package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
- package/Tests/Types/TextRandomGeneration.test.ts +211 -0
- package/Tests/UI/Components/Button.test.tsx +175 -1
- package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
- package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
- package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
- package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
- package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
- package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
- package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
- package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
- package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
- package/Tests/UI/Components/List.test.tsx +9 -2
- package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
- package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
- package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
- package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
- package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
- package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
- package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
- package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
- package/Tests/UI/Components/Skeleton.test.tsx +71 -0
- package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
- package/Tests/UI/Components/Tabs.test.tsx +24 -0
- package/Tests/UI/Components/Toast.test.tsx +130 -7
- package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
- package/Tests/UI/Utils/Dropdown.test.ts +423 -0
- package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
- package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
- package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
- package/Tests/Utils/API.test.ts +16 -2
- package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
- package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
- package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
- package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
- package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
- package/Types/Permission.ts +35 -0
- package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
- package/Types/PushNotification/PushNotificationMessage.ts +15 -0
- package/Types/PushNotification/PushNotificationRequest.ts +8 -16
- package/Types/Service/ServiceLanguage.ts +144 -0
- package/Types/Text.ts +111 -19
- package/UI/Components/Button/Button.tsx +27 -14
- package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
- package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
- package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
- package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
- package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
- package/UI/Components/CommandPalette/Types.ts +49 -0
- package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
- package/UI/Components/Dropdown/Dropdown.tsx +6 -1
- package/UI/Components/Feed/FeedItem.tsx +1 -1
- package/UI/Components/List/List.tsx +37 -5
- package/UI/Components/List/ListSkeleton.tsx +54 -0
- package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +6 -1
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
- package/UI/Components/Modal/Modal.tsx +2 -2
- package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
- package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
- package/UI/Components/Navbar/NavBar.tsx +14 -1
- package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
- package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
- package/UI/Components/SideOver/SideOver.tsx +37 -2
- package/UI/Components/Skeleton/Skeleton.tsx +53 -0
- package/UI/Components/Table/Table.tsx +74 -44
- package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
- package/UI/Components/Tabs/Tab.tsx +1 -1
- package/UI/Components/Toast/Toast.tsx +118 -53
- package/UI/Components/Toast/ToastInit.tsx +82 -32
- package/UI/Styles/Theme.css +40 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
- package/UI/Utils/ModelListCache.ts +188 -0
- package/UI/Utils/Project.ts +29 -0
- package/Utils/API.ts +6 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
- package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
- package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
- package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
- package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +69 -13
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/UserCallAPI.js +42 -38
- package/build/dist/Server/API/UserCallAPI.js.map +1 -1
- package/build/dist/Server/API/UserEmailAPI.js +42 -38
- package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
- package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
- package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
- package/build/dist/Server/API/UserPushAPI.js +95 -2
- package/build/dist/Server/API/UserPushAPI.js.map +1 -1
- package/build/dist/Server/API/UserSmsAPI.js +42 -38
- package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
- package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
- package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
- package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +74 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +5 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/PushNotificationService.js +69 -30
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +43 -7
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/UserCallService.js +54 -22
- package/build/dist/Server/Services/UserCallService.js.map +1 -1
- package/build/dist/Server/Services/UserEmailService.js +78 -17
- package/build/dist/Server/Services/UserEmailService.js.map +1 -1
- package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
- package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
- package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserPushService.js +77 -0
- package/build/dist/Server/Services/UserPushService.js.map +1 -1
- package/build/dist/Server/Services/UserSmsService.js +50 -17
- package/build/dist/Server/Services/UserSmsService.js.map +1 -1
- package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
- package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
- package/build/dist/Server/Utils/ChannelVerification.js +348 -0
- package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +13 -12
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/TotpAuth.js +127 -8
- package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
- package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
- package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
- package/build/dist/Server/Utils/VerificationCode.js +120 -0
- package/build/dist/Server/Utils/VerificationCode.js.map +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
- package/build/dist/Types/Permission.js +33 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
- package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
- package/build/dist/Types/Service/ServiceLanguage.js +96 -0
- package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
- package/build/dist/Types/Text.js +82 -17
- package/build/dist/Types/Text.js.map +1 -1
- package/build/dist/UI/Components/Button/Button.js +22 -14
- package/build/dist/UI/Components/Button/Button.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
- package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
- package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
- package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
- package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
- package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
- package/build/dist/UI/Components/List/List.js +19 -5
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
- package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +2 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
- package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
- package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +35 -24
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
- package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
- package/build/dist/UI/Components/Tabs/Tab.js +1 -1
- package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
- package/build/dist/UI/Components/Toast/Toast.js +77 -23
- package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
- package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
- package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/ModelListCache.js +126 -0
- package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
- package/build/dist/UI/Utils/Project.js +24 -1
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/build/dist/Utils/API.js +6 -1
- package/build/dist/Utils/API.js.map +1 -1
- package/jest.config.json +1 -1
- package/package.json +2 -3
- package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
- package/Tests/__mocks__/otpauth.js +0 -30
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* PasswordHash carries a pre-existing TS5.9 diagnostic that fails any suite
|
|
3
|
+
* whose runtime require graph reaches it (DatabaseService, the base class of
|
|
4
|
+
* every concrete service, imports it). Nothing password-related is under
|
|
5
|
+
* test here, so the module is replaced WITH A FACTORY — an automock would
|
|
6
|
+
* still require (and type-check) the real file.
|
|
7
|
+
*/
|
|
8
|
+
jest.mock("../../../Server/Utils/PasswordHash", () => {
|
|
9
|
+
return {
|
|
10
|
+
__esModule: true,
|
|
11
|
+
default: {
|
|
12
|
+
hash: jest.fn(),
|
|
13
|
+
verify: jest.fn(),
|
|
14
|
+
generateSalt: jest.fn(),
|
|
15
|
+
needsUpgrade: jest.fn(),
|
|
16
|
+
applyPepper: jest.fn(),
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
jest.mock("../../../Server/Utils/Express", () => {
|
|
22
|
+
return {
|
|
23
|
+
getRouter: () => {
|
|
24
|
+
return mockRouter;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
jest.mock("../../../Server/Utils/Response", () => {
|
|
30
|
+
return {
|
|
31
|
+
sendEntityArrayResponse: jest.fn().mockImplementation((...args: []) => {
|
|
32
|
+
return args;
|
|
33
|
+
}),
|
|
34
|
+
sendJsonObjectResponse: jest.fn().mockImplementation((...args: []) => {
|
|
35
|
+
return args;
|
|
36
|
+
}),
|
|
37
|
+
sendEmptySuccessResponse: jest.fn(),
|
|
38
|
+
sendEntityResponse: jest.fn().mockImplementation((...args: []) => {
|
|
39
|
+
return args;
|
|
40
|
+
}),
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
/*
|
|
45
|
+
* The real DatabaseService pulls in the whole server dependency graph. The
|
|
46
|
+
* suite drives BaseAPI.getList with hand-built service stubs instead, so the
|
|
47
|
+
* class is reduced to a mock constructor. getList's stock-hook check compares
|
|
48
|
+
* service.onBeforeFind against DatabaseService.prototype.onBeforeFind BY
|
|
49
|
+
* REFERENCE, so the mock's prototype must carry a real function — a bare
|
|
50
|
+
* jest.fn() constructor's prototype has no onBeforeFind, and every stub would
|
|
51
|
+
* then pass the compare as undefined === undefined, never exercising the
|
|
52
|
+
* inherited-vs-own mechanics the gate relies on. Stock-path stubs inherit the
|
|
53
|
+
* hook (createServiceStub below); override-path stubs shadow it with their
|
|
54
|
+
* own function. The returned instance still needs the methods that concrete
|
|
55
|
+
* services invoke at module load (the require graph instantiates them all),
|
|
56
|
+
* mirroring BaseAPI.test.ts.
|
|
57
|
+
*/
|
|
58
|
+
jest.mock("../../../Server/Services/DatabaseService", () => {
|
|
59
|
+
const DatabaseServiceMock: jest.Mock = jest.fn().mockImplementation(() => {
|
|
60
|
+
return {
|
|
61
|
+
countBy: jest.fn(),
|
|
62
|
+
findBy: jest.fn(),
|
|
63
|
+
findOneById: jest.fn(),
|
|
64
|
+
deleteOneBy: jest.fn(),
|
|
65
|
+
deleteOneById: jest.fn(),
|
|
66
|
+
updateOneById: jest.fn(),
|
|
67
|
+
updateOneBy: jest.fn(),
|
|
68
|
+
create: jest.fn(),
|
|
69
|
+
hardDeleteItemsOlderThanInDays: jest.fn(),
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* The shared stock hook: a named function on the prototype, so the gate's
|
|
75
|
+
* reference compare works against the same shared-function-inheritance
|
|
76
|
+
* shape it sees in production.
|
|
77
|
+
*/
|
|
78
|
+
function stockOnBeforeFind(findBy: unknown): Promise<unknown> {
|
|
79
|
+
return Promise.resolve(findBy);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
(
|
|
83
|
+
DatabaseServiceMock as unknown as {
|
|
84
|
+
prototype: { onBeforeFind: unknown };
|
|
85
|
+
}
|
|
86
|
+
).prototype.onBeforeFind = stockOnBeforeFind;
|
|
87
|
+
|
|
88
|
+
return DatabaseServiceMock;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
jest.mock(
|
|
92
|
+
"../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel",
|
|
93
|
+
() => {
|
|
94
|
+
return jest.fn().mockImplementation((initObject: GenericObject) => {
|
|
95
|
+
return {
|
|
96
|
+
...initObject,
|
|
97
|
+
getCrudApiPath: jest.fn().mockImplementation(() => {
|
|
98
|
+
return "/mock";
|
|
99
|
+
}),
|
|
100
|
+
getTableColumnMetadata: jest.fn().mockImplementation(() => {
|
|
101
|
+
return null;
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
jest.mock("../../../Server/Services/ProjectService", () => {
|
|
109
|
+
return {
|
|
110
|
+
getCurrentPlan: () => {
|
|
111
|
+
return {
|
|
112
|
+
currentPlan: "Free",
|
|
113
|
+
isSubscriptionUnpaid: false,
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
jest.mock("../../../Server/EnvironmentConfig", () => {
|
|
120
|
+
return {
|
|
121
|
+
...jest.requireActual("../../../Server/EnvironmentConfig"),
|
|
122
|
+
IsBillingEnabled: true,
|
|
123
|
+
LogLevel: "INFO",
|
|
124
|
+
DisableTelemetry: true,
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
import BaseAPI from "../../../Server/API/BaseAPI";
|
|
129
|
+
import DatabaseService from "../../../Server/Services/DatabaseService";
|
|
130
|
+
import {
|
|
131
|
+
ExpressResponse,
|
|
132
|
+
OneUptimeRequest,
|
|
133
|
+
} from "../../../Server/Utils/Express";
|
|
134
|
+
import Response from "../../../Server/Utils/Response";
|
|
135
|
+
import { mockRouter } from "./Helpers";
|
|
136
|
+
import { afterEach, describe, expect, it } from "@jest/globals";
|
|
137
|
+
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
138
|
+
import GenericObject from "../../../Types/GenericObject";
|
|
139
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
140
|
+
import PositiveNumber from "../../../Types/PositiveNumber";
|
|
141
|
+
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/typedef
|
|
143
|
+
const res = {
|
|
144
|
+
status: jest.fn().mockReturnThis(),
|
|
145
|
+
json: jest.fn().mockReturnThis(),
|
|
146
|
+
send: jest.fn().mockReturnThis(),
|
|
147
|
+
} as any as ExpressResponse;
|
|
148
|
+
|
|
149
|
+
type Deferred<T> = {
|
|
150
|
+
promise: Promise<T>;
|
|
151
|
+
resolve: (value: T) => void;
|
|
152
|
+
reject: (error: Error) => void;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
function createDeferred<T>(): Deferred<T> {
|
|
156
|
+
let resolveFn: ((value: T) => void) | null = null;
|
|
157
|
+
let rejectFn: ((error: Error) => void) | null = null;
|
|
158
|
+
|
|
159
|
+
const promise: Promise<T> = new Promise<T>(
|
|
160
|
+
(resolve: (value: T) => void, reject: (error: Error) => void) => {
|
|
161
|
+
resolveFn = resolve;
|
|
162
|
+
rejectFn = reject;
|
|
163
|
+
},
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
return {
|
|
167
|
+
promise,
|
|
168
|
+
resolve: resolveFn!,
|
|
169
|
+
reject: rejectFn!,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/*
|
|
174
|
+
* getList awaits a handful of internal steps (onBeforeList, the common-props
|
|
175
|
+
* builder) before dispatching the service calls; draining a generous number
|
|
176
|
+
* of microtask turns lets every already-startable step run without ever
|
|
177
|
+
* resolving the deferred service promises.
|
|
178
|
+
*/
|
|
179
|
+
async function flushMicrotasks(): Promise<void> {
|
|
180
|
+
for (let i: number = 0; i < 25; i++) {
|
|
181
|
+
await Promise.resolve();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
type ServiceStub = {
|
|
186
|
+
findBy: jest.Mock;
|
|
187
|
+
countBy: jest.Mock;
|
|
188
|
+
onBeforeFind?: (...args: Array<unknown>) => Promise<unknown>;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/*
|
|
192
|
+
* Stock-path stubs must INHERIT onBeforeFind from the mocked DatabaseService
|
|
193
|
+
* prototype — exactly how a concrete service that never overrides the hook
|
|
194
|
+
* holds it in production — so getList's reference compare is exercised for
|
|
195
|
+
* real. Override-path tests shadow it by assigning an own function.
|
|
196
|
+
*/
|
|
197
|
+
function createServiceStub(): ServiceStub {
|
|
198
|
+
const stub: ServiceStub = Object.create(
|
|
199
|
+
(DatabaseService as unknown as { prototype: Record<string, unknown> })
|
|
200
|
+
.prototype,
|
|
201
|
+
) as ServiceStub;
|
|
202
|
+
stub.findBy = jest.fn();
|
|
203
|
+
stub.countBy = jest.fn();
|
|
204
|
+
return stub;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function createApi(
|
|
208
|
+
service: ServiceStub,
|
|
209
|
+
): BaseAPI<BaseModel, DatabaseService<BaseModel>> {
|
|
210
|
+
return new BaseAPI<BaseModel, DatabaseService<BaseModel>>(
|
|
211
|
+
BaseModel,
|
|
212
|
+
service as unknown as DatabaseService<BaseModel>,
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function createListRequest(body?: JSONObject): OneUptimeRequest {
|
|
217
|
+
return {
|
|
218
|
+
query: {},
|
|
219
|
+
headers: {},
|
|
220
|
+
...(body ? { body } : {}),
|
|
221
|
+
} as unknown as OneUptimeRequest;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
describe("BaseAPI.getList findBy/countBy parallel dispatch", () => {
|
|
225
|
+
afterEach(() => {
|
|
226
|
+
jest.clearAllMocks();
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
describe("harness guard: the stock-hook compare stays non-degenerate", () => {
|
|
230
|
+
it("gives stock stubs the inherited prototype hook and override stubs their own", () => {
|
|
231
|
+
const proto: { onBeforeFind: unknown } = (
|
|
232
|
+
DatabaseService as unknown as {
|
|
233
|
+
prototype: { onBeforeFind: unknown };
|
|
234
|
+
}
|
|
235
|
+
).prototype;
|
|
236
|
+
|
|
237
|
+
/*
|
|
238
|
+
* The gate under test is a function-reference equality. If the mocked
|
|
239
|
+
* prototype ever loses its hook, both sides collapse to undefined and
|
|
240
|
+
* every stub — overridden or not — would take the parallel path, so
|
|
241
|
+
* pin that the two compares genuinely differ.
|
|
242
|
+
*/
|
|
243
|
+
expect(typeof proto.onBeforeFind).toBe("function");
|
|
244
|
+
|
|
245
|
+
const stockStub: ServiceStub = createServiceStub();
|
|
246
|
+
expect(stockStub.onBeforeFind).toBe(proto.onBeforeFind);
|
|
247
|
+
|
|
248
|
+
const overrideStub: ServiceStub = createServiceStub();
|
|
249
|
+
overrideStub.onBeforeFind = jest.fn() as unknown as (
|
|
250
|
+
...args: Array<unknown>
|
|
251
|
+
) => Promise<unknown>;
|
|
252
|
+
expect(overrideStub.onBeforeFind).not.toBe(proto.onBeforeFind);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
describe("service with the stock onBeforeFind hook (parallel path)", () => {
|
|
257
|
+
it("starts countBy before findBy has resolved, and sends the unchanged response envelope", async () => {
|
|
258
|
+
const service: ServiceStub = createServiceStub();
|
|
259
|
+
const api: BaseAPI<BaseModel, DatabaseService<BaseModel>> = createApi(
|
|
260
|
+
service,
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
const findDeferred: Deferred<Array<BaseModel>> =
|
|
264
|
+
createDeferred<Array<BaseModel>>();
|
|
265
|
+
const countDeferred: Deferred<PositiveNumber> =
|
|
266
|
+
createDeferred<PositiveNumber>();
|
|
267
|
+
|
|
268
|
+
service.findBy.mockReturnValue(findDeferred.promise);
|
|
269
|
+
service.countBy.mockReturnValue(countDeferred.promise);
|
|
270
|
+
|
|
271
|
+
const request: OneUptimeRequest = createListRequest();
|
|
272
|
+
const pending: Promise<void> = api.getList(request, res);
|
|
273
|
+
|
|
274
|
+
await flushMicrotasks();
|
|
275
|
+
|
|
276
|
+
/*
|
|
277
|
+
* The core of the change: with findBy still pending, countBy must
|
|
278
|
+
* already have been dispatched. The old sequential code awaited findBy
|
|
279
|
+
* to completion first, so countBy would not have been called here.
|
|
280
|
+
*/
|
|
281
|
+
expect(service.findBy).toHaveBeenCalledTimes(1);
|
|
282
|
+
expect(service.countBy).toHaveBeenCalledTimes(1);
|
|
283
|
+
|
|
284
|
+
const list: Array<BaseModel> = [
|
|
285
|
+
{ id: "mock" },
|
|
286
|
+
] as unknown as Array<BaseModel>;
|
|
287
|
+
const count: PositiveNumber = new PositiveNumber(42);
|
|
288
|
+
|
|
289
|
+
findDeferred.resolve(list);
|
|
290
|
+
countDeferred.resolve(count);
|
|
291
|
+
await pending;
|
|
292
|
+
|
|
293
|
+
// Same envelope as before: (req, res, list, count, entityType).
|
|
294
|
+
expect(Response.sendEntityArrayResponse).toHaveBeenCalledTimes(1);
|
|
295
|
+
expect(Response.sendEntityArrayResponse).toHaveBeenCalledWith(
|
|
296
|
+
request,
|
|
297
|
+
res,
|
|
298
|
+
list,
|
|
299
|
+
count,
|
|
300
|
+
BaseModel,
|
|
301
|
+
);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it("gives countBy its own copies of query and props so neither call can see the other's in-place edits", async () => {
|
|
305
|
+
const service: ServiceStub = createServiceStub();
|
|
306
|
+
const api: BaseAPI<BaseModel, DatabaseService<BaseModel>> = createApi(
|
|
307
|
+
service,
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
service.findBy.mockResolvedValue([]);
|
|
311
|
+
service.countBy.mockResolvedValue(new PositiveNumber(0));
|
|
312
|
+
|
|
313
|
+
const request: OneUptimeRequest = createListRequest({
|
|
314
|
+
query: { name: "zeta" },
|
|
315
|
+
select: { name: true },
|
|
316
|
+
sort: {},
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
await api.getList(request, res);
|
|
320
|
+
|
|
321
|
+
// eslint-disable-next-line @typescript-eslint/typedef
|
|
322
|
+
const findArgs = service.findBy.mock.calls[0]?.[0] as {
|
|
323
|
+
query: JSONObject;
|
|
324
|
+
props: JSONObject;
|
|
325
|
+
};
|
|
326
|
+
// eslint-disable-next-line @typescript-eslint/typedef
|
|
327
|
+
const countArgs = service.countBy.mock.calls[0]?.[0] as {
|
|
328
|
+
query: JSONObject;
|
|
329
|
+
props: JSONObject;
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
// Same effective query and props for both calls...
|
|
333
|
+
expect(countArgs.query).toEqual(findArgs.query);
|
|
334
|
+
expect(countArgs.query).toEqual({ name: "zeta" });
|
|
335
|
+
expect(countArgs.props).toEqual(findArgs.props);
|
|
336
|
+
|
|
337
|
+
// ...but distinct objects, so concurrent mutation cannot leak across.
|
|
338
|
+
expect(countArgs.query).not.toBe(findArgs.query);
|
|
339
|
+
expect(countArgs.props).not.toBe(findArgs.props);
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
it("rejects with findBy's error when findBy fails", async () => {
|
|
343
|
+
const service: ServiceStub = createServiceStub();
|
|
344
|
+
const api: BaseAPI<BaseModel, DatabaseService<BaseModel>> = createApi(
|
|
345
|
+
service,
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
const findDeferred: Deferred<Array<BaseModel>> =
|
|
349
|
+
createDeferred<Array<BaseModel>>();
|
|
350
|
+
const countDeferred: Deferred<PositiveNumber> =
|
|
351
|
+
createDeferred<PositiveNumber>();
|
|
352
|
+
|
|
353
|
+
service.findBy.mockReturnValue(findDeferred.promise);
|
|
354
|
+
service.countBy.mockReturnValue(countDeferred.promise);
|
|
355
|
+
|
|
356
|
+
const pending: Promise<void> = api.getList(createListRequest(), res);
|
|
357
|
+
const findError: Error = new Error("findBy failed");
|
|
358
|
+
const rejection: Promise<void> = expect(pending).rejects.toBe(findError);
|
|
359
|
+
|
|
360
|
+
await flushMicrotasks();
|
|
361
|
+
findDeferred.reject(findError);
|
|
362
|
+
countDeferred.resolve(new PositiveNumber(0));
|
|
363
|
+
|
|
364
|
+
await rejection;
|
|
365
|
+
expect(Response.sendEntityArrayResponse).not.toHaveBeenCalled();
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it("rejects with countBy's error when countBy fails", async () => {
|
|
369
|
+
const service: ServiceStub = createServiceStub();
|
|
370
|
+
const api: BaseAPI<BaseModel, DatabaseService<BaseModel>> = createApi(
|
|
371
|
+
service,
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
const findDeferred: Deferred<Array<BaseModel>> =
|
|
375
|
+
createDeferred<Array<BaseModel>>();
|
|
376
|
+
const countDeferred: Deferred<PositiveNumber> =
|
|
377
|
+
createDeferred<PositiveNumber>();
|
|
378
|
+
|
|
379
|
+
service.findBy.mockReturnValue(findDeferred.promise);
|
|
380
|
+
service.countBy.mockReturnValue(countDeferred.promise);
|
|
381
|
+
|
|
382
|
+
const pending: Promise<void> = api.getList(createListRequest(), res);
|
|
383
|
+
const countError: Error = new Error("countBy failed");
|
|
384
|
+
const rejection: Promise<void> = expect(pending).rejects.toBe(countError);
|
|
385
|
+
|
|
386
|
+
await flushMicrotasks();
|
|
387
|
+
countDeferred.reject(countError);
|
|
388
|
+
findDeferred.resolve([]);
|
|
389
|
+
|
|
390
|
+
await rejection;
|
|
391
|
+
expect(Response.sendEntityArrayResponse).not.toHaveBeenCalled();
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it("keeps findBy's error priority when both calls fail, even if countBy fails first", async () => {
|
|
395
|
+
const service: ServiceStub = createServiceStub();
|
|
396
|
+
const api: BaseAPI<BaseModel, DatabaseService<BaseModel>> = createApi(
|
|
397
|
+
service,
|
|
398
|
+
);
|
|
399
|
+
|
|
400
|
+
const findDeferred: Deferred<Array<BaseModel>> =
|
|
401
|
+
createDeferred<Array<BaseModel>>();
|
|
402
|
+
const countDeferred: Deferred<PositiveNumber> =
|
|
403
|
+
createDeferred<PositiveNumber>();
|
|
404
|
+
|
|
405
|
+
service.findBy.mockReturnValue(findDeferred.promise);
|
|
406
|
+
service.countBy.mockReturnValue(countDeferred.promise);
|
|
407
|
+
|
|
408
|
+
const pending: Promise<void> = api.getList(createListRequest(), res);
|
|
409
|
+
const findError: Error = new Error("findBy failed");
|
|
410
|
+
const countError: Error = new Error("countBy failed");
|
|
411
|
+
|
|
412
|
+
/*
|
|
413
|
+
* Sequentially, a double failure always surfaced findBy's error
|
|
414
|
+
* (countBy never even ran). The parallel path must keep that outcome
|
|
415
|
+
* regardless of which call happens to fail first.
|
|
416
|
+
*/
|
|
417
|
+
const rejection: Promise<void> = expect(pending).rejects.toBe(findError);
|
|
418
|
+
|
|
419
|
+
await flushMicrotasks();
|
|
420
|
+
countDeferred.reject(countError);
|
|
421
|
+
await flushMicrotasks();
|
|
422
|
+
findDeferred.reject(findError);
|
|
423
|
+
|
|
424
|
+
await rejection;
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
describe("service with an overridden onBeforeFind hook (sequential fallback)", () => {
|
|
429
|
+
/*
|
|
430
|
+
* Some services (ProjectService, the incident/alert privacy filters)
|
|
431
|
+
* mutate the shared query/props objects in place inside onBeforeFind, and
|
|
432
|
+
* the count has always inherited those mutations by running afterwards.
|
|
433
|
+
* For such services the pre-change sequential order — and the shared
|
|
434
|
+
* object identity that carries the mutations — must be preserved.
|
|
435
|
+
*/
|
|
436
|
+
it("does not start countBy until findBy resolves, and shares the query/props objects between the calls", async () => {
|
|
437
|
+
const service: ServiceStub = createServiceStub();
|
|
438
|
+
service.onBeforeFind = jest.fn() as unknown as (
|
|
439
|
+
...args: Array<unknown>
|
|
440
|
+
) => Promise<unknown>;
|
|
441
|
+
const api: BaseAPI<BaseModel, DatabaseService<BaseModel>> = createApi(
|
|
442
|
+
service,
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
const findDeferred: Deferred<Array<BaseModel>> =
|
|
446
|
+
createDeferred<Array<BaseModel>>();
|
|
447
|
+
const countDeferred: Deferred<PositiveNumber> =
|
|
448
|
+
createDeferred<PositiveNumber>();
|
|
449
|
+
|
|
450
|
+
service.findBy.mockReturnValue(findDeferred.promise);
|
|
451
|
+
service.countBy.mockReturnValue(countDeferred.promise);
|
|
452
|
+
|
|
453
|
+
const request: OneUptimeRequest = createListRequest({
|
|
454
|
+
query: { name: "zeta" },
|
|
455
|
+
select: { name: true },
|
|
456
|
+
sort: {},
|
|
457
|
+
});
|
|
458
|
+
const pending: Promise<void> = api.getList(request, res);
|
|
459
|
+
|
|
460
|
+
await flushMicrotasks();
|
|
461
|
+
|
|
462
|
+
expect(service.findBy).toHaveBeenCalledTimes(1);
|
|
463
|
+
expect(service.countBy).not.toHaveBeenCalled();
|
|
464
|
+
|
|
465
|
+
const list: Array<BaseModel> = [] as Array<BaseModel>;
|
|
466
|
+
findDeferred.resolve(list);
|
|
467
|
+
await flushMicrotasks();
|
|
468
|
+
|
|
469
|
+
expect(service.countBy).toHaveBeenCalledTimes(1);
|
|
470
|
+
|
|
471
|
+
// eslint-disable-next-line @typescript-eslint/typedef
|
|
472
|
+
const findArgs = service.findBy.mock.calls[0]?.[0] as {
|
|
473
|
+
query: JSONObject;
|
|
474
|
+
props: JSONObject;
|
|
475
|
+
};
|
|
476
|
+
// eslint-disable-next-line @typescript-eslint/typedef
|
|
477
|
+
const countArgs = service.countBy.mock.calls[0]?.[0] as {
|
|
478
|
+
query: JSONObject;
|
|
479
|
+
props: JSONObject;
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
// Identity, not just equality: in-place hook mutations must carry over.
|
|
483
|
+
expect(countArgs.query).toBe(findArgs.query);
|
|
484
|
+
expect(countArgs.props).toBe(findArgs.props);
|
|
485
|
+
|
|
486
|
+
const count: PositiveNumber = new PositiveNumber(0);
|
|
487
|
+
countDeferred.resolve(count);
|
|
488
|
+
await pending;
|
|
489
|
+
|
|
490
|
+
expect(Response.sendEntityArrayResponse).toHaveBeenCalledWith(
|
|
491
|
+
request,
|
|
492
|
+
res,
|
|
493
|
+
list,
|
|
494
|
+
count,
|
|
495
|
+
BaseModel,
|
|
496
|
+
);
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
it("never starts countBy when findBy fails", async () => {
|
|
500
|
+
const service: ServiceStub = createServiceStub();
|
|
501
|
+
service.onBeforeFind = jest.fn() as unknown as (
|
|
502
|
+
...args: Array<unknown>
|
|
503
|
+
) => Promise<unknown>;
|
|
504
|
+
const api: BaseAPI<BaseModel, DatabaseService<BaseModel>> = createApi(
|
|
505
|
+
service,
|
|
506
|
+
);
|
|
507
|
+
|
|
508
|
+
const findError: Error = new Error("findBy failed");
|
|
509
|
+
service.findBy.mockRejectedValue(findError);
|
|
510
|
+
service.countBy.mockResolvedValue(new PositiveNumber(0));
|
|
511
|
+
|
|
512
|
+
await expect(api.getList(createListRequest(), res)).rejects.toBe(
|
|
513
|
+
findError,
|
|
514
|
+
);
|
|
515
|
+
expect(service.countBy).not.toHaveBeenCalled();
|
|
516
|
+
expect(Response.sendEntityArrayResponse).not.toHaveBeenCalled();
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
});
|