@stacksjs/defaults 0.70.57 → 0.70.59
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/app/Actions/AI/AskAction.ts +40 -0
- package/app/Actions/AI/SummaryAction.ts +40 -0
- package/app/Actions/Auth/AuthUserAction.ts +13 -0
- package/app/Actions/Auth/CreateTokenAction.ts +64 -0
- package/app/Actions/Auth/DisableTwoFactorAction.ts +37 -0
- package/app/Actions/Auth/EnableTwoFactorAction.ts +37 -0
- package/app/Actions/Auth/GenerateAuthenticationAction.ts +51 -0
- package/app/Actions/Auth/GenerateRegistrationAction.ts +53 -0
- package/app/Actions/Auth/GenerateTwoFactorSecretAction.ts +26 -0
- package/app/Actions/Auth/ListTokensAction.ts +30 -0
- package/app/Actions/Auth/LoginAction.ts +73 -0
- package/app/Actions/Auth/LogoutAction.ts +16 -0
- package/app/Actions/Auth/LogoutAllAction.ts +28 -0
- package/app/Actions/Auth/RefreshTokenAction.ts +39 -0
- package/app/Actions/Auth/RegisterAction.ts +57 -0
- package/app/Actions/Auth/ResendVerificationAction.ts +24 -0
- package/app/Actions/Auth/RevokeTokenAction.ts +43 -0
- package/app/Actions/Auth/TestAbilitiesAction.ts +61 -0
- package/app/Actions/Auth/VerifyAuthenticationAction.ts +94 -0
- package/app/Actions/Auth/VerifyEmailAction.ts +25 -0
- package/app/Actions/Auth/VerifyRegistrationAction.ts +59 -0
- package/app/Actions/Auth/VerifyTwoFactorLoginAction.ts +57 -0
- package/app/Actions/Billable/CheckoutAction.ts +25 -0
- package/app/Actions/Buddy/BuddyBrowseAction.ts +34 -0
- package/app/Actions/Buddy/BuddyCancelAction.ts +32 -0
- package/app/Actions/Buddy/BuddyCommitAction.ts +25 -0
- package/app/Actions/Buddy/BuddyGitHubConnectAction.ts +40 -0
- package/app/Actions/Buddy/BuddyGitHubDisconnectAction.ts +19 -0
- package/app/Actions/Buddy/BuddyProcessAction.ts +65 -0
- package/app/Actions/Buddy/BuddyProcessStreamAction.ts +128 -0
- package/app/Actions/Buddy/BuddyPushAction.ts +21 -0
- package/app/Actions/Buddy/BuddyRepoOpenAction.ts +44 -0
- package/app/Actions/Buddy/BuddyRepoValidateAction.ts +35 -0
- package/app/Actions/Buddy/BuddySettingsAction.ts +21 -0
- package/app/Actions/Buddy/BuddySettingsUpdateAction.ts +46 -0
- package/app/Actions/Buddy/BuddyStateAction.ts +28 -0
- package/app/Actions/Buddy/BuddyTitleAction.ts +49 -0
- package/app/Actions/Buddy/CommandsAction.ts +802 -0
- package/app/Actions/Buddy/JobCancelAction.ts +32 -0
- package/app/Actions/Buddy/JobRetryAction.ts +49 -0
- package/app/Actions/Buddy/JobsListAction.ts +141 -0
- package/app/Actions/Buddy/ScheduleListAction.ts +52 -0
- package/app/Actions/Buddy/VersionsAction.ts +12 -0
- package/app/Actions/Cms/AuthorDestroyAction.ts +21 -0
- package/app/Actions/Cms/AuthorIndexAction.ts +14 -0
- package/app/Actions/Cms/AuthorShowAction.ts +19 -0
- package/app/Actions/Cms/AuthorStoreAction.ts +20 -0
- package/app/Actions/Cms/AuthorUpdateAction.ts +24 -0
- package/app/Actions/Cms/CategorizableDestroyAction.ts +16 -0
- package/app/Actions/Cms/CategorizableIndexAction.ts +14 -0
- package/app/Actions/Cms/CategorizableShowAction.ts +16 -0
- package/app/Actions/Cms/CategorizableStoreAction.ts +42 -0
- package/app/Actions/Cms/CategorizableUpdateAction.ts +38 -0
- package/app/Actions/Cms/CommentDestroyAction.ts +16 -0
- package/app/Actions/Cms/CommentIndexAction.ts +17 -0
- package/app/Actions/Cms/CommentShowAction.ts +16 -0
- package/app/Actions/Cms/CommentStoreAction.ts +39 -0
- package/app/Actions/Cms/CommentUpdateAction.ts +37 -0
- package/app/Actions/Cms/PageDestroyAction.ts +16 -0
- package/app/Actions/Cms/PageIndexAction.ts +14 -0
- package/app/Actions/Cms/PageStoreAction.ts +31 -0
- package/app/Actions/Cms/PageUpdateAction.ts +27 -0
- package/app/Actions/Cms/PostDestroyAction.ts +17 -0
- package/app/Actions/Cms/PostIndexAction.ts +14 -0
- package/app/Actions/Cms/PostShowAction.ts +16 -0
- package/app/Actions/Cms/PostStoreAction.ts +37 -0
- package/app/Actions/Cms/PostUpdateAction.ts +32 -0
- package/app/Actions/Cms/PostViewsUpdateAction.ts +34 -0
- package/app/Actions/Cms/RssFeedAction.ts +59 -0
- package/app/Actions/Cms/SitemapAction.ts +60 -0
- package/app/Actions/Cms/TaggableDestroyAction.ts +16 -0
- package/app/Actions/Cms/TaggableIndexAction.ts +14 -0
- package/app/Actions/Cms/TaggableShowAction.ts +16 -0
- package/app/Actions/Cms/TaggableStoreAction.ts +36 -0
- package/app/Actions/Cms/TaggableUpdateAction.ts +37 -0
- package/app/Actions/Commerce/CouponDestroyAction.ts +18 -0
- package/app/Actions/Commerce/CouponIndexAction.ts +16 -0
- package/app/Actions/Commerce/CouponShowAction.ts +18 -0
- package/app/Actions/Commerce/CouponStoreAction.ts +21 -0
- package/app/Actions/Commerce/CouponUpdateAction.ts +31 -0
- package/app/Actions/Commerce/CustomerDestroyAction.ts +16 -0
- package/app/Actions/Commerce/CustomerIndexAction.ts +15 -0
- package/app/Actions/Commerce/CustomerShowAction.ts +18 -0
- package/app/Actions/Commerce/CustomerStoreAction.ts +29 -0
- package/app/Actions/Commerce/CustomerUpdateAction.ts +27 -0
- package/app/Actions/Commerce/DriverDestroyAction.ts +18 -0
- package/app/Actions/Commerce/GiftCardDestroyAction.ts +18 -0
- package/app/Actions/Commerce/GiftCardIndexAction.ts +16 -0
- package/app/Actions/Commerce/GiftCardShowAction.ts +18 -0
- package/app/Actions/Commerce/GiftCardStatsAction.ts +30 -0
- package/app/Actions/Commerce/GiftCardStoreAction.ts +35 -0
- package/app/Actions/Commerce/GiftCardUpdateAction.ts +26 -0
- package/app/Actions/Commerce/GiftCardUpdateBalanceAction.ts +36 -0
- package/app/Actions/Commerce/OrderDestroyAction.ts +18 -0
- package/app/Actions/Commerce/OrderExportAction.ts +15 -0
- package/app/Actions/Commerce/OrderIndexAction.ts +15 -0
- package/app/Actions/Commerce/OrderShowAction.ts +18 -0
- package/app/Actions/Commerce/OrderStoreAction.ts +32 -0
- package/app/Actions/Commerce/OrderUpdateAction.ts +34 -0
- package/app/Actions/Commerce/PaymentDestroyAction.ts +16 -0
- package/app/Actions/Commerce/PaymentFetchStatsAction.ts +31 -0
- package/app/Actions/Commerce/PaymentIndexAction.ts +15 -0
- package/app/Actions/Commerce/PaymentMonthlyTrendsAction.ts +21 -0
- package/app/Actions/Commerce/PaymentShowAction.ts +17 -0
- package/app/Actions/Commerce/PaymentStoreAction.ts +24 -0
- package/app/Actions/Commerce/PaymentUpdateAction.ts +35 -0
- package/app/Actions/Commerce/PrintDeviceDestroyAction.ts +18 -0
- package/app/Actions/Commerce/PrintDeviceIndexAction.ts +14 -0
- package/app/Actions/Commerce/PrintDeviceShowAction.ts +17 -0
- package/app/Actions/Commerce/PrintDeviceStoreAction.ts +27 -0
- package/app/Actions/Commerce/PrintDeviceUpdateAction.ts +27 -0
- package/app/Actions/Commerce/Product/ManufacturerDestroyAction.ts +20 -0
- package/app/Actions/Commerce/Product/ManufacturerIndexAction.ts +16 -0
- package/app/Actions/Commerce/Product/ManufacturerShowAction.ts +18 -0
- package/app/Actions/Commerce/Product/ManufacturerStoreAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductCategoryIndexAction.ts +16 -0
- package/app/Actions/Commerce/Product/ProductCategoryStoreAction.ts +16 -0
- package/app/Actions/Commerce/Product/ProductDestroyAction.ts +16 -0
- package/app/Actions/Commerce/Product/ProductIndexAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductManufacturerDestroyAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductManufacturerIndexAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductManufacturerShowAction.ts +16 -0
- package/app/Actions/Commerce/Product/ProductManufacturerStoreAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductManufacturerUpdateAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductShowAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductStoreAction.ts +17 -0
- package/app/Actions/Commerce/Product/ProductUnitDestroyAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductUnitIndexAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductUnitShowAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductUnitStoreAction.ts +15 -0
- package/app/Actions/Commerce/Product/ProductUpdateAction.ts +17 -0
- package/app/Actions/Commerce/Product/ProductVariantDestroyAction.ts +18 -0
- package/app/Actions/Commerce/Product/ProductVariantIndexAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductVariantShowAction.ts +17 -0
- package/app/Actions/Commerce/Product/ProductVariantStoreAction.ts +14 -0
- package/app/Actions/Commerce/Product/ProductVariantUpdateAction.ts +16 -0
- package/app/Actions/Commerce/ReceiptDestroyAction.ts +18 -0
- package/app/Actions/Commerce/ReceiptIndexAction.ts +14 -0
- package/app/Actions/Commerce/ReceiptShowAction.ts +18 -0
- package/app/Actions/Commerce/ReceiptStoreAction.ts +28 -0
- package/app/Actions/Commerce/ReceiptUpdateAction.ts +30 -0
- package/app/Actions/Commerce/ReviewIndexAction.ts +14 -0
- package/app/Actions/Commerce/ReviewShowAction.ts +16 -0
- package/app/Actions/Commerce/ReviewStoreAction.ts +26 -0
- package/app/Actions/Commerce/ReviewUpdateAction.ts +28 -0
- package/app/Actions/Commerce/Shipping/DeliveryRouteDestroyAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DeliveryRouteIndexAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/DeliveryRouteShowAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DeliveryRouteStoreAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/DeliveryRouteUpdateAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DigitalDeliveryDestroyAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DigitalDeliveryIndexAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/DigitalDeliveryShowAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DigitalDeliveryStoreAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DigitalDeliveryUpdateAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DriverIndexAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/DriverShowAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/DriverStoreAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/DriverUpdateAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/LicenseKeyDestroyAction.ts +20 -0
- package/app/Actions/Commerce/Shipping/LicenseKeyIndexAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/LicenseKeyShowAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/LicenseKeyStoreAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/LicenseKeyUpdateAction.ts +18 -0
- package/app/Actions/Commerce/Shipping/ShippingMethodDestroyAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingMethodIndexAction.ts +14 -0
- package/app/Actions/Commerce/Shipping/ShippingMethodShowAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingMethodStoreAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingMethodUpdateAction.ts +15 -0
- package/app/Actions/Commerce/Shipping/ShippingRateDestroyAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingRateIndexAction.ts +14 -0
- package/app/Actions/Commerce/Shipping/ShippingRateShowAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingRateStoreAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingRateUpdateAction.ts +17 -0
- package/app/Actions/Commerce/Shipping/ShippingZoneDestroyAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingZoneIndexAction.ts +14 -0
- package/app/Actions/Commerce/Shipping/ShippingZoneShowAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingZoneStoreAction.ts +16 -0
- package/app/Actions/Commerce/Shipping/ShippingZoneUpdateAction.ts +15 -0
- package/app/Actions/Commerce/TaxRateDestroyAction.ts +16 -0
- package/app/Actions/Commerce/TaxRateIndexAction.ts +14 -0
- package/app/Actions/Commerce/TaxRateShowAction.ts +17 -0
- package/app/Actions/Commerce/TaxRateStoreAction.ts +24 -0
- package/app/Actions/Commerce/TaxRateUpdateAction.ts +24 -0
- package/app/Actions/Commerce/WaitlistProductAnalyticsAction.ts +29 -0
- package/app/Actions/Commerce/WaitlistProductDestroyAction.ts +16 -0
- package/app/Actions/Commerce/WaitlistProductIndexAction.ts +14 -0
- package/app/Actions/Commerce/WaitlistProductQuantityDistributionAction.ts +32 -0
- package/app/Actions/Commerce/WaitlistProductShowAction.ts +16 -0
- package/app/Actions/Commerce/WaitlistProductStatusAction.ts +37 -0
- package/app/Actions/Commerce/WaitlistProductStoreAction.ts +27 -0
- package/app/Actions/Commerce/WaitlistProductTimeSeriesAction.ts +25 -0
- package/app/Actions/Commerce/WaitlistProductUpdateAction.ts +29 -0
- package/app/Actions/Commerce/WaitlistRestaurantDashboardAction.ts +29 -0
- package/app/Actions/Commerce/WaitlistRestaurantDestroyAction.ts +16 -0
- package/app/Actions/Commerce/WaitlistRestaurantIndexAction.ts +14 -0
- package/app/Actions/Commerce/WaitlistRestaurantShowAction.ts +16 -0
- package/app/Actions/Commerce/WaitlistRestaurantStoreAction.ts +31 -0
- package/app/Actions/Commerce/WaitlistRestaurantUpdateAction.ts +33 -0
- package/app/Actions/ContactAction.ts +72 -0
- package/app/Actions/Dashboard/Actions/CreateAction.ts +11 -0
- package/app/Actions/Dashboard/Actions/GetActionCount.ts +12 -0
- package/app/Actions/Dashboard/Actions/GetActions.ts +19 -0
- package/app/Actions/Dashboard/Analytics/BlogAnalyticsAction.ts +58 -0
- package/app/Actions/Dashboard/Analytics/BrowserAnalyticsAction.ts +42 -0
- package/app/Actions/Dashboard/Analytics/CommerceAnalyticsAction.ts +64 -0
- package/app/Actions/Dashboard/Analytics/CountryAnalyticsAction.ts +41 -0
- package/app/Actions/Dashboard/Analytics/DeviceAnalyticsAction.ts +58 -0
- package/app/Actions/Dashboard/Analytics/EventAnalyticsAction.ts +90 -0
- package/app/Actions/Dashboard/Analytics/MarketingAnalyticsAction.ts +76 -0
- package/app/Actions/Dashboard/Analytics/PageAnalyticsAction.ts +45 -0
- package/app/Actions/Dashboard/Analytics/ReferrerAnalyticsAction.ts +72 -0
- package/app/Actions/Dashboard/Analytics/SalesAnalyticsAction.ts +73 -0
- package/app/Actions/Dashboard/Analytics/WebAnalyticsAction.ts +114 -0
- package/app/Actions/Dashboard/Auth/MeAction.ts +84 -0
- package/app/Actions/Dashboard/BuddyDashboardAction.ts +34 -0
- package/app/Actions/Dashboard/Ci/RepoRunJobsAction.ts +60 -0
- package/app/Actions/Dashboard/Ci/RepoRunsAction.ts +67 -0
- package/app/Actions/Dashboard/Ci/RunnerHistoryAction.ts +58 -0
- package/app/Actions/Dashboard/Ci/StatusAction.ts +73 -0
- package/app/Actions/Dashboard/Ci/failure-notifier.ts +214 -0
- package/app/Actions/Dashboard/Ci/runner-pressure-monitor.ts +259 -0
- package/app/Actions/Dashboard/Cloud/CloudIndexAction.ts +61 -0
- package/app/Actions/Dashboard/Commands/CreateCommand.ts +11 -0
- package/app/Actions/Dashboard/Commands/GetAverageCommandTime.ts +12 -0
- package/app/Actions/Dashboard/Commands/GetCommandCount.ts +12 -0
- package/app/Actions/Dashboard/Commands/GetCommandSuccessRate.ts +12 -0
- package/app/Actions/Dashboard/Commands/GetCommands.ts +12 -0
- package/app/Actions/Dashboard/Commerce/CommerceCouponsAction.ts +48 -0
- package/app/Actions/Dashboard/Commerce/CommerceCustomersAction.ts +48 -0
- package/app/Actions/Dashboard/Commerce/CommerceDashboardAction.ts +98 -0
- package/app/Actions/Dashboard/Commerce/CommerceDeliveryAction.ts +65 -0
- package/app/Actions/Dashboard/Commerce/CommerceGiftCardsAction.ts +48 -0
- package/app/Actions/Dashboard/Commerce/CommerceOrdersAction.ts +51 -0
- package/app/Actions/Dashboard/Commerce/CommercePaymentsAction.ts +59 -0
- package/app/Actions/Dashboard/Commerce/CommerceProductsAction.ts +50 -0
- package/app/Actions/Dashboard/Commerce/CommerceTaxesAction.ts +46 -0
- package/app/Actions/Dashboard/Commerce/PosIndexAction.ts +57 -0
- package/app/Actions/Dashboard/Commerce/ReviewIndexAction.ts +51 -0
- package/app/Actions/Dashboard/Content/AuthorIndexAction.ts +51 -0
- package/app/Actions/Dashboard/Content/CategoryIndexAction.ts +27 -0
- package/app/Actions/Dashboard/Content/CommentIndexAction.ts +41 -0
- package/app/Actions/Dashboard/Content/ContentDashboardAction.ts +54 -0
- package/app/Actions/Dashboard/Content/FileIndexAction.ts +24 -0
- package/app/Actions/Dashboard/Content/PageIndexAction.ts +25 -0
- package/app/Actions/Dashboard/Content/PostIndexAction.ts +102 -0
- package/app/Actions/Dashboard/Content/SeoIndexAction.ts +17 -0
- package/app/Actions/Dashboard/Content/TagIndexAction.ts +23 -0
- package/app/Actions/Dashboard/CreateDnsRecords.ts +11 -0
- package/app/Actions/Dashboard/CreateMailbox.ts +11 -0
- package/app/Actions/Dashboard/DashboardActivityAction.ts +58 -0
- package/app/Actions/Dashboard/DashboardHealthAction.ts +52 -0
- package/app/Actions/Dashboard/DashboardHomeAction.ts +83 -0
- package/app/Actions/Dashboard/DashboardStatsAction.ts +48 -0
- package/app/Actions/Dashboard/Data/AccessTokenIndexAction.ts +65 -0
- package/app/Actions/Dashboard/Data/ActivityIndexAction.ts +28 -0
- package/app/Actions/Dashboard/Data/DataDashboardAction.ts +67 -0
- package/app/Actions/Dashboard/Data/SubscriberIndexAction.ts +48 -0
- package/app/Actions/Dashboard/Data/TeamIndexAction.ts +43 -0
- package/app/Actions/Dashboard/Data/UserIndexAction.ts +48 -0
- package/app/Actions/Dashboard/Deployments/CreateDeployment.ts +11 -0
- package/app/Actions/Dashboard/Deployments/GetAverageDeploymentTime.ts +15 -0
- package/app/Actions/Dashboard/Deployments/GetDeployScript.ts +12 -0
- package/app/Actions/Dashboard/Deployments/GetDeploymentCount.ts +12 -0
- package/app/Actions/Dashboard/Deployments/GetDeploymentLiveTerminalOutput.ts +12 -0
- package/app/Actions/Dashboard/Deployments/GetDeployments.ts +20 -0
- package/app/Actions/Dashboard/Deployments/GetRecentDeployments.ts +12 -0
- package/app/Actions/Dashboard/Deployments/UpdateDeployScript.ts +11 -0
- package/app/Actions/Dashboard/GetDnsRecords.ts +12 -0
- package/app/Actions/Dashboard/GetEmailInboxes.ts +12 -0
- package/app/Actions/Dashboard/GetProjects.ts +13 -0
- package/app/Actions/Dashboard/GetRecentCommits.ts +13 -0
- package/app/Actions/Dashboard/Inbox/InboxIndexAction.ts +144 -0
- package/app/Actions/Dashboard/Inbox/InboxShowAction.ts +89 -0
- package/app/Actions/Dashboard/Infrastructure/CommandIndexAction.ts +18 -0
- package/app/Actions/Dashboard/Infrastructure/DnsIndexAction.ts +101 -0
- package/app/Actions/Dashboard/Infrastructure/EnvironmentIndexAction.ts +67 -0
- package/app/Actions/Dashboard/Infrastructure/InsightsAction.ts +29 -0
- package/app/Actions/Dashboard/Infrastructure/LogIndexAction.ts +50 -0
- package/app/Actions/Dashboard/Infrastructure/MailboxIndexAction.ts +85 -0
- package/app/Actions/Dashboard/Infrastructure/PermissionIndexAction.ts +54 -0
- package/app/Actions/Dashboard/Infrastructure/RequestIndexAction.ts +44 -0
- package/app/Actions/Dashboard/Infrastructure/ServerIndexAction.ts +101 -0
- package/app/Actions/Dashboard/Jobs/CreateJob.ts +11 -0
- package/app/Actions/Dashboard/Jobs/GetAverageJobTime.ts +12 -0
- package/app/Actions/Dashboard/Jobs/GetJobHistory.ts +12 -0
- package/app/Actions/Dashboard/Jobs/GetJobs.ts +11 -0
- package/app/Actions/Dashboard/Jobs/GetJobsPerMinute.ts +12 -0
- package/app/Actions/Dashboard/Jobs/JobIndexAction.ts +136 -0
- package/app/Actions/Dashboard/Jobs/JobRetryAction.ts +23 -0
- package/app/Actions/Dashboard/Jobs/JobStatsAction.ts +49 -0
- package/app/Actions/Dashboard/Kanban/BoardDestroyAction.ts +84 -0
- package/app/Actions/Dashboard/Kanban/BoardShowAction.ts +215 -0
- package/app/Actions/Dashboard/Kanban/BoardStoreAction.ts +98 -0
- package/app/Actions/Dashboard/Kanban/BoardUpdateAction.ts +96 -0
- package/app/Actions/Dashboard/Kanban/BoardsIndexAction.ts +81 -0
- package/app/Actions/Dashboard/Kanban/BoardsReorderAction.ts +80 -0
- package/app/Actions/Dashboard/Kanban/CardAssigneesSyncAction.ts +103 -0
- package/app/Actions/Dashboard/Kanban/CardCommentDestroyAction.ts +33 -0
- package/app/Actions/Dashboard/Kanban/CardCommentStoreAction.ts +82 -0
- package/app/Actions/Dashboard/Kanban/CardDestroyAction.ts +48 -0
- package/app/Actions/Dashboard/Kanban/CardLabelsSyncAction.ts +103 -0
- package/app/Actions/Dashboard/Kanban/CardShowAction.ts +122 -0
- package/app/Actions/Dashboard/Kanban/CardStoreAction.ts +112 -0
- package/app/Actions/Dashboard/Kanban/CardUpdateAction.ts +91 -0
- package/app/Actions/Dashboard/Kanban/CardsReorderAction.ts +148 -0
- package/app/Actions/Dashboard/Kanban/ColumnDestroyAction.ts +59 -0
- package/app/Actions/Dashboard/Kanban/ColumnStoreAction.ts +94 -0
- package/app/Actions/Dashboard/Kanban/ColumnUpdateAction.ts +89 -0
- package/app/Actions/Dashboard/Kanban/ColumnsReorderAction.ts +85 -0
- package/app/Actions/Dashboard/Kanban/LabelDestroyAction.ts +41 -0
- package/app/Actions/Dashboard/Kanban/LabelStoreAction.ts +70 -0
- package/app/Actions/Dashboard/Kanban/LabelUpdateAction.ts +83 -0
- package/app/Actions/Dashboard/Kanban/UsersListAction.ts +36 -0
- package/app/Actions/Dashboard/Library/CreateComponent.ts +11 -0
- package/app/Actions/Dashboard/Library/CreateFunction.ts +11 -0
- package/app/Actions/Dashboard/Library/DependencyIndexAction.ts +92 -0
- package/app/Actions/Dashboard/Library/GetAverageReleaseTime.ts +12 -0
- package/app/Actions/Dashboard/Library/GetComponents.ts +24 -0
- package/app/Actions/Dashboard/Library/GetComponentsDownloadCount.ts +12 -0
- package/app/Actions/Dashboard/Library/GetDownloadCount.ts +12 -0
- package/app/Actions/Dashboard/Library/GetFunctions.ts +22 -0
- package/app/Actions/Dashboard/Library/GetFunctionsDownloadCount.ts +12 -0
- package/app/Actions/Dashboard/Library/GetReleaseCount.ts +12 -0
- package/app/Actions/Dashboard/Library/GetReleases.ts +28 -0
- package/app/Actions/Dashboard/Library/PackageIndexAction.ts +26 -0
- package/app/Actions/Dashboard/Marketing/CampaignIndexAction.ts +45 -0
- package/app/Actions/Dashboard/Marketing/ListIndexAction.ts +43 -0
- package/app/Actions/Dashboard/Marketing/SocialPostIndexAction.ts +47 -0
- package/app/Actions/Dashboard/Models/GetModels.ts +39 -0
- package/app/Actions/Dashboard/Models/GetSubscriberCount.ts +12 -0
- package/app/Actions/Dashboard/Models/GetUserCount.ts +12 -0
- package/app/Actions/Dashboard/Models/ModelShowAction.ts +131 -0
- package/app/Actions/Dashboard/Models/ModelsIndexAction.ts +169 -0
- package/app/Actions/Dashboard/Notifications/CreateNotification.ts +11 -0
- package/app/Actions/Dashboard/Notifications/GetAverageNotificationTime.ts +12 -0
- package/app/Actions/Dashboard/Notifications/GetNotificationCount.ts +12 -0
- package/app/Actions/Dashboard/Notifications/GetNotificationDeliveryRate.ts +12 -0
- package/app/Actions/Dashboard/Notifications/GetNotificationHistory.ts +12 -0
- package/app/Actions/Dashboard/Notifications/GetNotifications.ts +12 -0
- package/app/Actions/Dashboard/Notifications/NotificationDashboardAction.ts +43 -0
- package/app/Actions/Dashboard/Queries/QueryIndexAction.ts +22 -0
- package/app/Actions/Dashboard/Queue/QueueRetryFailedAction.ts +22 -0
- package/app/Actions/Dashboard/Queue/QueueStatsAction.ts +98 -0
- package/app/Actions/Dashboard/Queue/QueueWorkersAction.ts +46 -0
- package/app/Actions/Dashboard/Rbac/PermissionDestroyAction.ts +33 -0
- package/app/Actions/Dashboard/Rbac/PermissionStoreAction.ts +53 -0
- package/app/Actions/Dashboard/Rbac/PermissionsIndexAction.ts +34 -0
- package/app/Actions/Dashboard/Rbac/RoleDestroyAction.ts +35 -0
- package/app/Actions/Dashboard/Rbac/RolePermissionsShowAction.ts +45 -0
- package/app/Actions/Dashboard/Rbac/RolePermissionsSyncAction.ts +63 -0
- package/app/Actions/Dashboard/Rbac/RoleStoreAction.ts +58 -0
- package/app/Actions/Dashboard/Rbac/RolesIndexAction.ts +36 -0
- package/app/Actions/Dashboard/Rbac/UserRolesShowAction.ts +40 -0
- package/app/Actions/Dashboard/Rbac/UserRolesSyncAction.ts +65 -0
- package/app/Actions/Dashboard/Rbac/UsersListAction.ts +39 -0
- package/app/Actions/Dashboard/Realtime/RealtimeStatsAction.ts +50 -0
- package/app/Actions/Dashboard/Releases/ReleaseIndexAction.ts +21 -0
- package/app/Actions/Dashboard/Requests/GetAverageRequestTime.ts +12 -0
- package/app/Actions/Dashboard/Requests/GetRequestCount.ts +12 -0
- package/app/Actions/Dashboard/Requests/GetRequestSuccessRate.ts +12 -0
- package/app/Actions/Dashboard/Requests/GetRequests.ts +12 -0
- package/app/Actions/Dashboard/Search/GlobalSearchAction.ts +26 -0
- package/app/Actions/Dashboard/ServiceHealthAction.ts +243 -0
- package/app/Actions/Dashboard/Settings/MailSettingsGetAction.ts +20 -0
- package/app/Actions/Dashboard/Settings/MailSettingsUpdateAction.ts +10 -0
- package/app/Actions/Dashboard/Settings/SettingsIndexAction.ts +40 -0
- package/app/Actions/Dashboard/Settings/UpdateAiConfig.ts +27 -0
- package/app/Actions/Dashboard/Settings/UpdateAnalyticsConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateAppConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateCacheConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateCliConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateCloudConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateDatabaseConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateDnsConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateDocsConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateEmailConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateEnvConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateErrorsConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateFileSystemsConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateGitConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateHashingConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateLibraryConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateLoggerConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateNotificationConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdatePaymentConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdatePortsConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateQueueConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateSearchEngineConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateSecurityConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateServicesConfig.ts +38 -0
- package/app/Actions/Dashboard/Settings/UpdateStorageConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateTeamConfig.ts +11 -0
- package/app/Actions/Dashboard/Settings/UpdateUiConfig.ts +11 -0
- package/app/Actions/HealthAction.ts +112 -0
- package/app/Actions/InstallAction.ts +83 -0
- package/app/Actions/Locale/SetLocaleAction.ts +51 -0
- package/app/Actions/LogAction.ts +42 -0
- package/app/Actions/Logs/LogFetchStatsAction.ts +50 -0
- package/app/Actions/Logs/LogIndexOrmAction.ts +13 -0
- package/app/Actions/Logs/LogShowOrmAction.ts +17 -0
- package/app/Actions/Logs/LogStoreOrmAction.ts +16 -0
- package/app/Actions/Logs/LogUpdateOrmAction.ts +20 -0
- package/app/Actions/Monitoring/ErrorDestroyAction.ts +25 -0
- package/app/Actions/Monitoring/ErrorGroupAction.ts +21 -0
- package/app/Actions/Monitoring/ErrorIgnoreAction.ts +25 -0
- package/app/Actions/Monitoring/ErrorIndexAction.ts +14 -0
- package/app/Actions/Monitoring/ErrorResolveAction.ts +25 -0
- package/app/Actions/Monitoring/ErrorShowAction.ts +19 -0
- package/app/Actions/Monitoring/ErrorStatsAction.ts +14 -0
- package/app/Actions/Monitoring/ErrorTimelineAction.ts +14 -0
- package/app/Actions/Monitoring/ErrorUnresolveAction.ts +25 -0
- package/app/Actions/NotifyUser.ts +10 -0
- package/app/Actions/Password/PasswordResetAction.ts +54 -0
- package/app/Actions/Password/SendPasswordResetEmailAction.ts +66 -0
- package/app/Actions/Password/VerifyResetTokenAction.ts +27 -0
- package/app/Actions/Payment/CancelSubscriptionAction.ts +20 -0
- package/app/Actions/Payment/CreateCheckoutAction.ts +28 -0
- package/app/Actions/Payment/CreateInvoiceSubscription.ts +18 -0
- package/app/Actions/Payment/CreatePaymentIntentAction.ts +31 -0
- package/app/Actions/Payment/CreateSetupIntentAction.ts +20 -0
- package/app/Actions/Payment/CreateSubscriptionAction.ts +23 -0
- package/app/Actions/Payment/DeleteDefaultPaymentAction.ts +18 -0
- package/app/Actions/Payment/FetchActiveSubscriptionAction.ts +18 -0
- package/app/Actions/Payment/FetchDefaultPaymentMethodAction.ts +18 -0
- package/app/Actions/Payment/FetchPaymentCustomerAction.ts +18 -0
- package/app/Actions/Payment/FetchPaymentMethodsAction.ts +18 -0
- package/app/Actions/Payment/FetchProductAction.ts +15 -0
- package/app/Actions/Payment/FetchTransactionHistoryAction.ts +18 -0
- package/app/Actions/Payment/FetchUserSubscriptionsAction.ts +18 -0
- package/app/Actions/Payment/SetDefaultPaymentAction.ts +20 -0
- package/app/Actions/Payment/SetUserDefaultPaymentAction.ts +20 -0
- package/app/Actions/Payment/StorePaymentMethodAction.ts +20 -0
- package/app/Actions/Payment/StoreTransactionAction.ts +20 -0
- package/app/Actions/Payment/UpdateCustomerAction.ts +24 -0
- package/app/Actions/Payment/UpdateDefaultPaymentMethodAction.ts +18 -0
- package/app/Actions/Payment/UpdateSubscriptionAction.ts +22 -0
- package/app/Actions/Queue/FetchQueuesAction.ts +14 -0
- package/app/Actions/README.md +61 -0
- package/app/Actions/Realtime/FetchWebsocketsAction.ts +14 -0
- package/app/Actions/RobotsAction.ts +61 -0
- package/app/Actions/SendWelcomeEmail.ts +40 -0
- package/app/Actions/SitemapAction.ts +234 -0
- package/app/Actions/Storefront/AddToCartAction.ts +153 -0
- package/app/Actions/Storefront/CheckoutContactAction.ts +50 -0
- package/app/Actions/Storefront/CheckoutShippingAction.ts +61 -0
- package/app/Actions/Storefront/GetCartAction.ts +58 -0
- package/app/Actions/Storefront/PlaceOrderAction.ts +195 -0
- package/app/Actions/Storefront/SubmitReviewAction.ts +140 -0
- package/app/Actions/Storefront/UpdateCartItemAction.ts +83 -0
- package/app/Actions/Storefront/_shipping.ts +64 -0
- package/app/Actions/SubscriberEmailAction.ts +60 -0
- package/app/Actions/TestErrorAction.ts +163 -0
- package/app/Actions/UnsubscribeAction.ts +107 -0
- package/app/Actions/UploadTestAction.ts +57 -0
- package/app/Broadcasts/OrderShipped.ts +57 -0
- package/app/Commands/Inspire.ts +57 -0
- package/app/Commands/README.md +84 -0
- package/app/Commands.ts +38 -0
- package/app/Controllers/ComingSoonController.ts +9 -0
- package/app/Controllers/QueryController.ts +373 -0
- package/app/Events.ts +14 -0
- package/app/Gates.ts +107 -0
- package/app/Jobs/ExampleJob.ts +20 -0
- package/app/Jobs/ExampleTwoJob.ts +12 -0
- package/app/Jobs/PruneModelsJob.ts +61 -0
- package/app/Jobs/PruneQueryLogsJob.ts +51 -0
- package/app/Jobs/README.md +79 -0
- package/app/Jobs/SendCampaignJob.ts +201 -0
- package/app/Jobs/SendEmailJob.ts +52 -0
- package/app/Jobs/SendPasswordResetEmailJob.ts +44 -0
- package/app/Jobs/SyncSearchIndexJob.ts +64 -0
- package/app/Listener.ts +84 -0
- package/app/Listeners/Console.ts +22 -0
- package/app/Listeners/README.md +47 -0
- package/app/Mail/OrderConfirmation.ts +60 -0
- package/app/Mail/SubscriptionConfirmation.ts +41 -0
- package/app/Middleware/Abilities.ts +53 -0
- package/app/Middleware/Api.ts +26 -0
- package/app/Middleware/Auth.ts +59 -0
- package/app/Middleware/Can.ts +68 -0
- package/app/Middleware/Compress.ts +213 -0
- package/app/Middleware/Cors.ts +320 -0
- package/app/Middleware/Csrf.ts +224 -0
- package/app/Middleware/EnsureEmailIsVerified.ts +28 -0
- package/app/Middleware/Env.ts +24 -0
- package/app/Middleware/EnvDevelopment.ts +19 -0
- package/app/Middleware/EnvLocal.ts +19 -0
- package/app/Middleware/EnvNotDevelopment.ts +19 -0
- package/app/Middleware/EnvNotLocal.ts +19 -0
- package/app/Middleware/EnvNotProduction.ts +19 -0
- package/app/Middleware/EnvNotStaging.ts +19 -0
- package/app/Middleware/EnvProduction.ts +19 -0
- package/app/Middleware/EnvStaging.ts +19 -0
- package/app/Middleware/Guest.ts +25 -0
- package/app/Middleware/Logger.ts +20 -0
- package/app/Middleware/Maintenance.ts +36 -0
- package/app/Middleware/Permission.ts +42 -0
- package/app/Middleware/README.md +48 -0
- package/app/Middleware/Role.ts +42 -0
- package/app/Middleware/Signed.ts +31 -0
- package/app/Middleware/Team.ts +36 -0
- package/app/Middleware/Throttle.ts +96 -0
- package/app/Middleware.ts +35 -0
- package/app/Models/Activity.ts +94 -0
- package/app/Models/Board.ts +103 -0
- package/app/Models/BoardColumn.ts +87 -0
- package/app/Models/Campaign.ts +239 -0
- package/app/Models/CampaignSend.ts +107 -0
- package/app/Models/Card.ts +117 -0
- package/app/Models/CardComment.ts +68 -0
- package/app/Models/Comment.ts +108 -0
- package/app/Models/Content/Author.ts +104 -0
- package/app/Models/Content/Page.ts +99 -0
- package/app/Models/Content/Post.ts +144 -0
- package/app/Models/Deployment.ts +116 -0
- package/app/Models/EmailList.ts +126 -0
- package/app/Models/EmailListSubscriber.ts +91 -0
- package/app/Models/Error.ts +70 -0
- package/app/Models/FailedJob.ts +62 -0
- package/app/Models/Job.ts +63 -0
- package/app/Models/Label.ts +66 -0
- package/app/Models/Log.ts +110 -0
- package/app/Models/Notification.ts +118 -0
- package/app/Models/PaymentMethod.ts +98 -0
- package/app/Models/PaymentProduct.ts +91 -0
- package/app/Models/PaymentTransaction.ts +78 -0
- package/app/Models/README.md +31 -0
- package/app/Models/Release.ts +89 -0
- package/app/Models/Request.ts +114 -0
- package/app/Models/SocialPost.ts +136 -0
- package/app/Models/Subscriber.ts +89 -0
- package/app/Models/SubscriberEmail.ts +55 -0
- package/app/Models/Subscription.ts +153 -0
- package/app/Models/Tag.ts +82 -0
- package/app/Models/Team.ts +72 -0
- package/app/Models/User.ts +134 -0
- package/app/Models/commerce/Cart.ts +139 -0
- package/app/Models/commerce/CartItem.ts +137 -0
- package/app/Models/commerce/Category.ts +105 -0
- package/app/Models/commerce/Coupon.ts +181 -0
- package/app/Models/commerce/Customer.ts +132 -0
- package/app/Models/commerce/DeliveryRoute.ts +93 -0
- package/app/Models/commerce/DigitalDelivery.ts +105 -0
- package/app/Models/commerce/Driver.ts +97 -0
- package/app/Models/commerce/GiftCard.ts +191 -0
- package/app/Models/commerce/LicenseKey.ts +87 -0
- package/app/Models/commerce/LoyaltyPoint.ts +107 -0
- package/app/Models/commerce/LoyaltyReward.ts +124 -0
- package/app/Models/commerce/Manufacturer.ts +84 -0
- package/app/Models/commerce/Order.ts +142 -0
- package/app/Models/commerce/OrderItem.ts +51 -0
- package/app/Models/commerce/Payment.ts +163 -0
- package/app/Models/commerce/PrintDevice.ts +117 -0
- package/app/Models/commerce/Product.ts +148 -0
- package/app/Models/commerce/ProductUnit.ts +107 -0
- package/app/Models/commerce/ProductVariant.ts +106 -0
- package/app/Models/commerce/Receipt.ts +128 -0
- package/app/Models/commerce/Review.ts +140 -0
- package/app/Models/commerce/ShippingMethod.ts +97 -0
- package/app/Models/commerce/ShippingRate.ts +74 -0
- package/app/Models/commerce/ShippingZone.ts +111 -0
- package/app/Models/commerce/TaxRate.ts +114 -0
- package/app/Models/commerce/Transaction.ts +126 -0
- package/app/Models/commerce/WaitlistProduct.ts +149 -0
- package/app/Models/commerce/WaitlistRestaurant.ts +187 -0
- package/app/Models/realtime/Websocket.ts +77 -0
- package/app/Notifications/README.md +31 -0
- package/app/Notifications/Welcome.ts +32 -0
- package/app/Policies/PostPolicy.ts +131 -0
- package/app/README.md +23 -0
- package/app/Routes.ts +47 -0
- package/app/Scheduler.ts +28 -0
- package/app/Storefront/CartCookie.ts +109 -0
- package/package.json +3 -2
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { getUserRoles } from '@stacksjs/auth'
|
|
3
|
+
|
|
4
|
+
interface MeResponse {
|
|
5
|
+
user: {
|
|
6
|
+
id: number
|
|
7
|
+
name: string | null
|
|
8
|
+
email: string | null
|
|
9
|
+
} | null
|
|
10
|
+
roles: string[]
|
|
11
|
+
/**
|
|
12
|
+
* Permissive defaults for the un-authenticated case (e.g. the dev dashboard
|
|
13
|
+
* on localhost where no bearer token is required). Surfaces are role-gated
|
|
14
|
+
* via `useRole()` which falls back to these when `user` is null, so the
|
|
15
|
+
* dashboard remains usable without auth.
|
|
16
|
+
*/
|
|
17
|
+
unauthenticated?: true
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* `GET /api/dashboard/auth/me`
|
|
22
|
+
*
|
|
23
|
+
* Returns the currently-authenticated user plus the names of every role
|
|
24
|
+
* they hold. Powers the dashboard's `useRole()` composable
|
|
25
|
+
* ([stacksjs/stacks#1843](https://github.com/stacksjs/stacks/issues/1843))
|
|
26
|
+
* which gates dev-mode surfaces like CI tracking (#1844) and (eventually)
|
|
27
|
+
* client-mode hiding of infra surfaces.
|
|
28
|
+
*
|
|
29
|
+
* Auth model: this endpoint is intentionally **not** behind the `auth`
|
|
30
|
+
* middleware. The dashboard runs locally for `buddy dev --dashboard` with
|
|
31
|
+
* no bearer token at all, and we don't want every dashboard load to flash
|
|
32
|
+
* a 401 in the network tab. Instead:
|
|
33
|
+
*
|
|
34
|
+
* - If the request carries a valid bearer token, the framework's auth
|
|
35
|
+
* middleware already populated `request.user` — we return that user
|
|
36
|
+
* plus their roles.
|
|
37
|
+
* - If not, we return `{ user: null, roles: [], unauthenticated: true }`.
|
|
38
|
+
* The composable's "no auth → assume dev" default kicks in client-side,
|
|
39
|
+
* so the dashboard stays usable.
|
|
40
|
+
*
|
|
41
|
+
* In production where the dashboard sits behind auth, deploy with the
|
|
42
|
+
* `auth` middleware applied to the `/api/dashboard` group — the endpoint
|
|
43
|
+
* will then return real user/role data and `useRole()` will see the
|
|
44
|
+
* server-side identity.
|
|
45
|
+
*/
|
|
46
|
+
export default new Action({
|
|
47
|
+
name: 'Dashboard Auth Me',
|
|
48
|
+
description: 'Returns the authenticated user + their RBAC roles for dashboard role gating.',
|
|
49
|
+
method: 'GET',
|
|
50
|
+
apiResponse: true,
|
|
51
|
+
async handle(request) {
|
|
52
|
+
const user = (request as any)?.user ?? (request as any)?._authenticatedUser ?? null
|
|
53
|
+
|
|
54
|
+
if (!user || typeof user !== 'object' || typeof (user as { id?: unknown }).id !== 'number') {
|
|
55
|
+
const res: MeResponse = { user: null, roles: [], unauthenticated: true }
|
|
56
|
+
return res
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const userId = (user as { id: number }).id
|
|
60
|
+
|
|
61
|
+
let roles: string[] = []
|
|
62
|
+
try {
|
|
63
|
+
const records = await getUserRoles(userId)
|
|
64
|
+
roles = records.map(r => r.name)
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
// RBAC store not configured, migrations not run, or DB unreachable.
|
|
68
|
+
// Empty roles → useRole will fall back to its dev default. We don't
|
|
69
|
+
// want to 500 the dashboard just because the role tables haven't
|
|
70
|
+
// been migrated yet on a fresh project.
|
|
71
|
+
console.warn('[dashboard/auth/me] getUserRoles failed:', err instanceof Error ? err.message : err)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const res: MeResponse = {
|
|
75
|
+
user: {
|
|
76
|
+
id: userId,
|
|
77
|
+
name: (user as { name?: string | null }).name ?? null,
|
|
78
|
+
email: (user as { email?: string | null }).email ?? null,
|
|
79
|
+
},
|
|
80
|
+
roles,
|
|
81
|
+
}
|
|
82
|
+
return res
|
|
83
|
+
},
|
|
84
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
|
|
3
|
+
export default new Action({
|
|
4
|
+
name: 'BuddyDashboardAction',
|
|
5
|
+
description: 'Returns Buddy CLI dashboard data including commands, output, and stats.',
|
|
6
|
+
method: 'GET',
|
|
7
|
+
async handle() {
|
|
8
|
+
const commands = [
|
|
9
|
+
{ command: 'buddy build', description: 'Build the application', lastRun: '5m ago', status: 'success' },
|
|
10
|
+
{ command: 'buddy dev', description: 'Start development server', lastRun: 'Running', status: 'running' },
|
|
11
|
+
{ command: 'buddy test', description: 'Run test suite', lastRun: '1h ago', status: 'success' },
|
|
12
|
+
{ command: 'buddy lint', description: 'Run linter', lastRun: '30m ago', status: 'success' },
|
|
13
|
+
{ command: 'buddy deploy', description: 'Deploy to production', lastRun: '2d ago', status: 'success' },
|
|
14
|
+
{ command: 'buddy migrate', description: 'Run database migrations', lastRun: '1d ago', status: 'success' },
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
const recentOutput = `[14:32:45] Starting development server...
|
|
18
|
+
[14:32:46] Compiling TypeScript...
|
|
19
|
+
[14:32:48] Compiled successfully in 2.3s
|
|
20
|
+
[14:32:48] Server running at http://localhost:3000
|
|
21
|
+
[14:32:48] Hot reload enabled
|
|
22
|
+
[14:32:50] Connected to database
|
|
23
|
+
[14:32:50] Ready for requests`
|
|
24
|
+
|
|
25
|
+
const stats = [
|
|
26
|
+
{ label: 'Commands Run', value: '1,234' },
|
|
27
|
+
{ label: 'Avg Build Time', value: '2.3s' },
|
|
28
|
+
{ label: 'Test Coverage', value: '89%' },
|
|
29
|
+
{ label: 'Last Deploy', value: '2d ago' },
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
return { commands, recentOutput, stats }
|
|
33
|
+
},
|
|
34
|
+
})
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { dashboard as dashboardConfig } from '@stacksjs/config'
|
|
3
|
+
import { fetchRunJobs } from '@stacksjs/github'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `GET /api/dashboard/ci/repos/:owner/:name/runs/:runId/jobs`
|
|
7
|
+
* (stacksjs/stacks#1848).
|
|
8
|
+
*
|
|
9
|
+
* Returns the job-level breakdown for a single workflow run —
|
|
10
|
+
* surfaced when the user expands a failing row in the drilldown
|
|
11
|
+
* drawer. Pricier than the run list (one round-trip per request),
|
|
12
|
+
* so the page only fires this on demand.
|
|
13
|
+
*
|
|
14
|
+
* Same auth + scope model as `RepoRunsAction`: org must be in
|
|
15
|
+
* `config.dashboard.ci.orgs` for the endpoint to engage.
|
|
16
|
+
*/
|
|
17
|
+
export default new Action({
|
|
18
|
+
name: 'Dashboard CI Repo Run Jobs',
|
|
19
|
+
description: 'Job-level breakdown for a single workflow run (drilldown expand).',
|
|
20
|
+
method: 'GET',
|
|
21
|
+
apiResponse: true,
|
|
22
|
+
async handle(request) {
|
|
23
|
+
const ci = dashboardConfig?.ci
|
|
24
|
+
|
|
25
|
+
if (!ci?.enabled) {
|
|
26
|
+
return { jobs: [], disabled: true }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const owner = String((request as any)?.params?.owner ?? (request as any)?.param?.('owner') ?? '').trim()
|
|
30
|
+
const repo = String((request as any)?.params?.name ?? (request as any)?.param?.('name') ?? '').trim()
|
|
31
|
+
const runIdRaw = (request as any)?.params?.runId ?? (request as any)?.param?.('runId') ?? null
|
|
32
|
+
const runId = Number(runIdRaw)
|
|
33
|
+
if (!owner || !repo) {
|
|
34
|
+
return { error: 'Both `owner` and `name` route params are required.', status: 400 }
|
|
35
|
+
}
|
|
36
|
+
if (!Number.isFinite(runId) || runId <= 0) {
|
|
37
|
+
return { error: '`runId` must be a positive integer.', status: 400 }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const allowedOrgs = ci.orgs ?? []
|
|
41
|
+
if (allowedOrgs.length > 0 && !allowedOrgs.includes(owner)) {
|
|
42
|
+
return { error: 'Org not in `config.dashboard.ci.orgs`.', status: 403 }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const jobs = await fetchRunJobs(owner, repo, runId)
|
|
47
|
+
return { owner, repo, runId, jobs }
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
console.error('[dashboard/ci] RepoRunJobsAction failed:', err)
|
|
51
|
+
return {
|
|
52
|
+
owner,
|
|
53
|
+
repo,
|
|
54
|
+
runId,
|
|
55
|
+
jobs: [],
|
|
56
|
+
error: err instanceof Error ? err.message : 'unknown error',
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
})
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { dashboard as dashboardConfig } from '@stacksjs/config'
|
|
3
|
+
import { fetchWorkflowRuns } from '@stacksjs/github'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `GET /api/dashboard/ci/repos/:owner/:name/runs?limit=N`
|
|
7
|
+
* (stacksjs/stacks#1848).
|
|
8
|
+
*
|
|
9
|
+
* Returns the N most recent workflow runs for a single repo. Used by
|
|
10
|
+
* the CI surface's drilldown drawer — clicking a repo card opens
|
|
11
|
+
* this and renders a timeline.
|
|
12
|
+
*
|
|
13
|
+
* Auth model mirrors the CI status endpoint:
|
|
14
|
+
* - When the CI surface is disabled (`config.dashboard.ci.enabled
|
|
15
|
+
* === false`), responds with an empty list rather than a 4xx so
|
|
16
|
+
* the drawer renders an empty-state instead of an error.
|
|
17
|
+
* - When `GITHUB_TOKEN` is missing, the helper bubbles an error
|
|
18
|
+
* up through `fetchWorkflowRuns`; we catch it here and surface
|
|
19
|
+
* it cleanly to the page.
|
|
20
|
+
*/
|
|
21
|
+
export default new Action({
|
|
22
|
+
name: 'Dashboard CI Repo Runs',
|
|
23
|
+
description: 'Latest N workflow runs for a single repo (drilldown).',
|
|
24
|
+
method: 'GET',
|
|
25
|
+
apiResponse: true,
|
|
26
|
+
async handle(request) {
|
|
27
|
+
const ci = dashboardConfig?.ci
|
|
28
|
+
|
|
29
|
+
if (!ci?.enabled) {
|
|
30
|
+
return { owner: null, repo: null, runs: [], disabled: true }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const owner = String((request as any)?.params?.owner ?? (request as any)?.param?.('owner') ?? '').trim()
|
|
34
|
+
const repo = String((request as any)?.params?.name ?? (request as any)?.param?.('name') ?? '').trim()
|
|
35
|
+
if (!owner || !repo) {
|
|
36
|
+
return { error: 'Both `owner` and `name` route params are required.', status: 400 }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Scope check: only fetch runs for orgs the user explicitly
|
|
40
|
+
// configured. Stops the endpoint from being a generic GH proxy.
|
|
41
|
+
const allowedOrgs = ci.orgs ?? []
|
|
42
|
+
if (allowedOrgs.length > 0 && !allowedOrgs.includes(owner)) {
|
|
43
|
+
return { error: 'Org not in `config.dashboard.ci.orgs`.', status: 403 }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const url = new URL(request.url ?? `http://localhost/`)
|
|
47
|
+
const rawLimit = Number(url.searchParams.get('limit') ?? '20')
|
|
48
|
+
const limit = Number.isFinite(rawLimit) && rawLimit > 0
|
|
49
|
+
? Math.min(Math.floor(rawLimit), 100)
|
|
50
|
+
: 20
|
|
51
|
+
const branch = url.searchParams.get('branch') || undefined
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const runs = await fetchWorkflowRuns(owner, repo, { limit, branch })
|
|
55
|
+
return { owner, repo, runs }
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
console.error('[dashboard/ci] RepoRunsAction failed:', err)
|
|
59
|
+
return {
|
|
60
|
+
owner,
|
|
61
|
+
repo,
|
|
62
|
+
runs: [],
|
|
63
|
+
error: err instanceof Error ? err.message : 'unknown error',
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { dashboard as dashboardConfig } from '@stacksjs/config'
|
|
3
|
+
import { fetchRunnerHistory } from './runner-pressure-monitor'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `GET /api/dashboard/ci/runner-history?org=stacksjs&limit=60`
|
|
7
|
+
* (stacksjs/stacks#1850).
|
|
8
|
+
*
|
|
9
|
+
* Returns the recent runner-sample history for one org so the CI
|
|
10
|
+
* page can render a small sparkline under each org's runner-pressure
|
|
11
|
+
* line. Bounded by `limit` (defaults to 60, hard cap 500) and the
|
|
12
|
+
* configured retention window — older samples aren't available
|
|
13
|
+
* because they've been pruned.
|
|
14
|
+
*
|
|
15
|
+
* Soft-errors to an empty samples array on any failure so the
|
|
16
|
+
* sparkline gracefully degrades to "no history yet" instead of
|
|
17
|
+
* yelling at the user.
|
|
18
|
+
*/
|
|
19
|
+
export default new Action({
|
|
20
|
+
name: 'Dashboard CI Runner History',
|
|
21
|
+
description: 'Recent runner-sample history for one org (sparkline data).',
|
|
22
|
+
method: 'GET',
|
|
23
|
+
apiResponse: true,
|
|
24
|
+
async handle(request) {
|
|
25
|
+
const ci = dashboardConfig?.ci
|
|
26
|
+
if (!ci?.enabled || !ci.alerts?.enabled) {
|
|
27
|
+
return { org: null, samples: [], disabled: true }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const url = new URL(request.url ?? 'http://localhost/')
|
|
31
|
+
const org = String(url.searchParams.get('org') ?? '').trim()
|
|
32
|
+
if (!org) {
|
|
33
|
+
return { error: '`org` query param is required.', status: 400 }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const allowedOrgs = ci.orgs ?? []
|
|
37
|
+
if (allowedOrgs.length > 0 && !allowedOrgs.includes(org)) {
|
|
38
|
+
return { error: 'Org not in `config.dashboard.ci.orgs`.', status: 403 }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const rawLimit = Number(url.searchParams.get('limit') ?? '60')
|
|
42
|
+
const limit = Number.isFinite(rawLimit) && rawLimit > 0
|
|
43
|
+
? Math.min(Math.floor(rawLimit), 500)
|
|
44
|
+
: 60
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const samples = await fetchRunnerHistory(org, {
|
|
48
|
+
limit,
|
|
49
|
+
retentionHours: ci.alerts.retentionHours,
|
|
50
|
+
})
|
|
51
|
+
return { org, samples }
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
console.error('[dashboard/ci] RunnerHistoryAction failed:', err)
|
|
55
|
+
return { org, samples: [], error: err instanceof Error ? err.message : 'unknown error' }
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
})
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { dashboard as dashboardConfig } from '@stacksjs/config'
|
|
3
|
+
import { getDashboardData } from '@stacksjs/github'
|
|
4
|
+
import { runCiFailureNotifier } from './failure-notifier'
|
|
5
|
+
import { runRunnerPressureMonitor } from './runner-pressure-monitor'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* `GET /api/dashboard/ci/status`
|
|
9
|
+
*
|
|
10
|
+
* Aggregated CI / runner snapshot consumed by `dashboard/ci/index.stx`.
|
|
11
|
+
* Reads org list + runner caps from `config/dashboard.ts:ci.*` so installs
|
|
12
|
+
* pick their own surface (stacksjs/stacks#1844). When the surface is
|
|
13
|
+
* disabled or no orgs are configured, returns an empty snapshot rather
|
|
14
|
+
* than throwing — the page renders an empty-state in that case.
|
|
15
|
+
*/
|
|
16
|
+
export default new Action({
|
|
17
|
+
name: 'Dashboard CI Status',
|
|
18
|
+
description: 'Aggregated CI/runner snapshot across the configured GitHub orgs.',
|
|
19
|
+
method: 'GET',
|
|
20
|
+
apiResponse: true,
|
|
21
|
+
async handle() {
|
|
22
|
+
const ci = dashboardConfig?.ci
|
|
23
|
+
|
|
24
|
+
if (!ci?.enabled || !ci.orgs || ci.orgs.length === 0) {
|
|
25
|
+
return {
|
|
26
|
+
repos: [],
|
|
27
|
+
fetchedAt: new Date().toISOString(),
|
|
28
|
+
total: 0,
|
|
29
|
+
passing: 0,
|
|
30
|
+
failing: 0,
|
|
31
|
+
pending: 0,
|
|
32
|
+
noRuns: 0,
|
|
33
|
+
runners: {},
|
|
34
|
+
disabled: !ci?.enabled,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
const data = await getDashboardData({
|
|
40
|
+
orgs: ci.orgs,
|
|
41
|
+
runnerCaps: ci.runnerCaps,
|
|
42
|
+
defaultRunnerCap: ci.runnerCapDefault,
|
|
43
|
+
ignoreRepos: ci.ignoreRepos,
|
|
44
|
+
})
|
|
45
|
+
// Failing-CI notifications (stacksjs/stacks#1849) +
|
|
46
|
+
// runner-pressure alerts (stacksjs/stacks#1850). Both
|
|
47
|
+
// fire-and-forget so they don't block the response on the
|
|
48
|
+
// notification + time-series persistence round-trips. Each
|
|
49
|
+
// internally guards on its own enabled flag, so unrelated
|
|
50
|
+
// projects pay no cost.
|
|
51
|
+
void runCiFailureNotifier(data)
|
|
52
|
+
void runRunnerPressureMonitor(data)
|
|
53
|
+
return data
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
// Most likely cause: GITHUB_TOKEN missing. Surface a clean error
|
|
57
|
+
// shape the page can render without leaking the env-var name to
|
|
58
|
+
// every browser viewing the dashboard.
|
|
59
|
+
console.error('[dashboard/ci] snapshot failed:', err)
|
|
60
|
+
return {
|
|
61
|
+
repos: [],
|
|
62
|
+
fetchedAt: new Date().toISOString(),
|
|
63
|
+
total: 0,
|
|
64
|
+
passing: 0,
|
|
65
|
+
failing: 0,
|
|
66
|
+
pending: 0,
|
|
67
|
+
noRuns: 0,
|
|
68
|
+
runners: {},
|
|
69
|
+
error: err instanceof Error ? err.message : 'unknown error',
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
})
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI failure notifier (stacksjs/stacks#1849).
|
|
3
|
+
*
|
|
4
|
+
* Bridges the pure `detectNewlyFailedRuns()` from @stacksjs/github
|
|
5
|
+
* with the persistence layer (the `ci_run_states` table) and the
|
|
6
|
+
* notification fan-out (`notify()` from @stacksjs/notifications).
|
|
7
|
+
*
|
|
8
|
+
* Lives in defaults — not in @stacksjs/github — because it pulls in
|
|
9
|
+
* the DB + notify infrastructure that the pure helper deliberately
|
|
10
|
+
* stays free of.
|
|
11
|
+
*
|
|
12
|
+
* Call from the CI StatusAction after a fresh snapshot resolves:
|
|
13
|
+
*
|
|
14
|
+
* void runCiFailureNotifier(snapshot)
|
|
15
|
+
*
|
|
16
|
+
* `void` because we don't want to block the response on the
|
|
17
|
+
* notification round-trips. The fan-out happens behind the user's
|
|
18
|
+
* back; any failure is logged but doesn't bubble.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import type { DashboardData, FailedTransition, PreviousRunState } from '@stacksjs/github'
|
|
22
|
+
import { dashboard as dashboardConfig } from '@stacksjs/config'
|
|
23
|
+
import { db } from '@stacksjs/database'
|
|
24
|
+
import { detectNewlyFailedRuns } from '@stacksjs/github'
|
|
25
|
+
import { notify } from '@stacksjs/notifications'
|
|
26
|
+
|
|
27
|
+
interface CiRunStateRow {
|
|
28
|
+
repo_full_name: string
|
|
29
|
+
last_conclusion: string | null
|
|
30
|
+
last_run_id: number | null
|
|
31
|
+
last_seen_at: string | null
|
|
32
|
+
last_notified_at: string | null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Load the dashboard's last-seen state for every repo in one query. */
|
|
36
|
+
async function loadPreviousStates(): Promise<Map<string, PreviousRunState>> {
|
|
37
|
+
const rows = await db.unsafe(
|
|
38
|
+
'SELECT repo_full_name, last_conclusion, last_run_id, last_notified_at FROM ci_run_states',
|
|
39
|
+
).execute() as CiRunStateRow[]
|
|
40
|
+
|
|
41
|
+
const map = new Map<string, PreviousRunState>()
|
|
42
|
+
for (const r of rows ?? []) {
|
|
43
|
+
map.set(r.repo_full_name, {
|
|
44
|
+
repoFullName: r.repo_full_name,
|
|
45
|
+
lastConclusion: r.last_conclusion,
|
|
46
|
+
lastRunId: r.last_run_id == null ? null : Number(r.last_run_id),
|
|
47
|
+
lastNotifiedAt: r.last_notified_at,
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
return map
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Upsert every repo in the snapshot's current state. Doesn't touch
|
|
55
|
+
* `last_notified_at` — that's owned by the notifier and only bumped
|
|
56
|
+
* when we actually fire.
|
|
57
|
+
*/
|
|
58
|
+
async function upsertSnapshotStates(snapshot: DashboardData): Promise<void> {
|
|
59
|
+
if (!snapshot.repos?.length) return
|
|
60
|
+
const nowIso = new Date().toISOString()
|
|
61
|
+
for (const r of snapshot.repos) {
|
|
62
|
+
const runId = parseRunIdFromUrl(r.runUrl)
|
|
63
|
+
// Two-step upsert — works across SQLite/MySQL/Postgres without
|
|
64
|
+
// dialect-specific ON CONFLICT shapes. Each repo is its own
|
|
65
|
+
// round-trip, but the table is small (one row per repo, so
|
|
66
|
+
// typically O(50) for a busy fleet) and this runs in the
|
|
67
|
+
// background after the response goes out.
|
|
68
|
+
const existing = await db.unsafe(
|
|
69
|
+
'SELECT repo_full_name FROM ci_run_states WHERE repo_full_name = ? LIMIT 1',
|
|
70
|
+
[r.fullName],
|
|
71
|
+
).execute() as Array<{ repo_full_name: string }>
|
|
72
|
+
if (existing?.length) {
|
|
73
|
+
await db.updateTable('ci_run_states').set({
|
|
74
|
+
last_conclusion: r.conclusion ?? r.status,
|
|
75
|
+
last_run_id: runId,
|
|
76
|
+
last_seen_at: nowIso,
|
|
77
|
+
updated_at: nowIso,
|
|
78
|
+
} as any).where('repo_full_name', '=', r.fullName).execute()
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
await db.insertInto('ci_run_states').values({
|
|
82
|
+
repo_full_name: r.fullName,
|
|
83
|
+
last_conclusion: r.conclusion ?? r.status,
|
|
84
|
+
last_run_id: runId,
|
|
85
|
+
last_seen_at: nowIso,
|
|
86
|
+
updated_at: nowIso,
|
|
87
|
+
} as any).execute()
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Bump `last_notified_at` for the repos we just fired on. */
|
|
93
|
+
async function markNotified(transitions: FailedTransition[]): Promise<void> {
|
|
94
|
+
if (!transitions.length) return
|
|
95
|
+
const nowIso = new Date().toISOString()
|
|
96
|
+
for (const t of transitions) {
|
|
97
|
+
await db.updateTable('ci_run_states')
|
|
98
|
+
.set({ last_notified_at: nowIso } as any)
|
|
99
|
+
.where('repo_full_name', '=', t.repoFullName)
|
|
100
|
+
.execute()
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function parseRunIdFromUrl(runUrl: string | null): number | null {
|
|
105
|
+
if (!runUrl) return null
|
|
106
|
+
const match = runUrl.match(/\/actions\/runs\/(\d+)/)
|
|
107
|
+
if (!match) return null
|
|
108
|
+
const id = Number(match[1])
|
|
109
|
+
return Number.isFinite(id) ? id : null
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** Build the human-readable payload for a single transition. */
|
|
113
|
+
function buildPayload(t: FailedTransition): { subject: string, body: string, data: Record<string, unknown> } {
|
|
114
|
+
const shortSha = t.commitSha ? t.commitSha.slice(0, 7) : ''
|
|
115
|
+
const commit = t.commitMessage ? `${shortSha} ${t.commitMessage.split('\n')[0]}` : shortSha
|
|
116
|
+
const workflow = t.workflowName ? ` (${t.workflowName})` : ''
|
|
117
|
+
const author = t.commitAuthor ? ` — ${t.commitAuthor}` : ''
|
|
118
|
+
const subject = `CI failed: ${t.repoFullName}${workflow}`
|
|
119
|
+
const lines = [
|
|
120
|
+
`${t.repoFullName}${workflow}`,
|
|
121
|
+
`Conclusion: ${t.conclusion}`,
|
|
122
|
+
]
|
|
123
|
+
if (commit) lines.push(`Commit: ${commit}${author}`)
|
|
124
|
+
if (t.runUrl) lines.push(`Run: ${t.runUrl}`)
|
|
125
|
+
return {
|
|
126
|
+
subject,
|
|
127
|
+
body: lines.join('\n'),
|
|
128
|
+
data: {
|
|
129
|
+
repoFullName: t.repoFullName,
|
|
130
|
+
runId: t.runId,
|
|
131
|
+
runUrl: t.runUrl,
|
|
132
|
+
conclusion: t.conclusion,
|
|
133
|
+
previousConclusion: t.previousConclusion,
|
|
134
|
+
commitSha: t.commitSha,
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Run the full detect → notify → persist cycle for a fresh snapshot.
|
|
141
|
+
*
|
|
142
|
+
* Caller pattern: `void runCiFailureNotifier(snapshot)` from the
|
|
143
|
+
* StatusAction. The cycle:
|
|
144
|
+
*
|
|
145
|
+
* 1. Skip entirely if `ci.notifications.enabled` is false.
|
|
146
|
+
* 2. Load previous states from `ci_run_states`.
|
|
147
|
+
* 3. Run the pure detector with the configured cooldown.
|
|
148
|
+
* 4. For each transition, fan out via `notify()` to every
|
|
149
|
+
* configured recipient × channel combination.
|
|
150
|
+
* - `chat` channel doesn't need recipients (it broadcasts to
|
|
151
|
+
* the configured Slack channel) — emit one notification with
|
|
152
|
+
* no recipient details.
|
|
153
|
+
* - Email / sms / database channels iterate the
|
|
154
|
+
* `recipients` list.
|
|
155
|
+
* 5. Upsert the current state for every repo (so next call has a
|
|
156
|
+
* diff baseline).
|
|
157
|
+
* 6. Bump `last_notified_at` for the repos we fired on.
|
|
158
|
+
*
|
|
159
|
+
* Errors at any step are logged and swallowed — a broken notifier
|
|
160
|
+
* must never take down the dashboard's read path.
|
|
161
|
+
*/
|
|
162
|
+
export async function runCiFailureNotifier(snapshot: DashboardData): Promise<void> {
|
|
163
|
+
const ci = dashboardConfig?.ci
|
|
164
|
+
const notifs = ci?.notifications
|
|
165
|
+
if (!notifs?.enabled || !snapshot.repos?.length)
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
const channels = (notifs.channels ?? ['chat']) as Array<'email' | 'sms' | 'chat' | 'database'>
|
|
169
|
+
const cooldownMs = (notifs.cooldownMinutes ?? 5) * 60_000
|
|
170
|
+
const recipients = notifs.recipients ?? []
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
const previousStates = await loadPreviousStates()
|
|
174
|
+
const transitions = detectNewlyFailedRuns(snapshot, previousStates, { cooldownMs })
|
|
175
|
+
|
|
176
|
+
// Fan out. Each transition fires once per (recipient × channel)
|
|
177
|
+
// combination. For channels that don't need a recipient (chat),
|
|
178
|
+
// we still fire once per transition with an empty recipient
|
|
179
|
+
// record — the chat driver ignores recipient fields.
|
|
180
|
+
for (const t of transitions) {
|
|
181
|
+
const payload = buildPayload(t)
|
|
182
|
+
const broadcastChannels = channels.filter(c => c === 'chat')
|
|
183
|
+
const recipientChannels = channels.filter(c => c !== 'chat')
|
|
184
|
+
|
|
185
|
+
if (broadcastChannels.length > 0) {
|
|
186
|
+
try {
|
|
187
|
+
await notify({}, payload, broadcastChannels, { ignorePreferences: true })
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
console.warn('[ci-failure-notifier] chat broadcast failed:', err)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (recipientChannels.length > 0 && recipients.length > 0) {
|
|
194
|
+
for (const r of recipients) {
|
|
195
|
+
try {
|
|
196
|
+
await notify(r, payload, recipientChannels, { ignorePreferences: true })
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
console.warn('[ci-failure-notifier] notify failed:', err)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Order matters: upsert states FIRST so the next refresh sees
|
|
206
|
+
// the current conclusion + run id, then mark-notified to update
|
|
207
|
+
// `last_notified_at` on the rows we fired on.
|
|
208
|
+
await upsertSnapshotStates(snapshot)
|
|
209
|
+
await markNotified(transitions)
|
|
210
|
+
}
|
|
211
|
+
catch (err) {
|
|
212
|
+
console.warn('[ci-failure-notifier] cycle failed:', err)
|
|
213
|
+
}
|
|
214
|
+
}
|