@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,61 @@
|
|
|
1
|
+
import { log } from '@stacksjs/logging'
|
|
2
|
+
|
|
3
|
+
interface PrunableModelConfig {
|
|
4
|
+
table: string
|
|
5
|
+
olderThanDays?: number
|
|
6
|
+
column?: string
|
|
7
|
+
query?: (qb: any) => any
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default class PruneModelsJob {
|
|
11
|
+
public static config = {
|
|
12
|
+
schedule: '0 0 * * *', // Daily at midnight
|
|
13
|
+
withoutOverlapping: true,
|
|
14
|
+
timeout: 5 * 60,
|
|
15
|
+
retries: 3,
|
|
16
|
+
retryAfter: [60, 120, 300],
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The models to prune and their configurations.
|
|
21
|
+
* Add entries here to register prunable models.
|
|
22
|
+
*/
|
|
23
|
+
private static prunableModels: PrunableModelConfig[] = []
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Register a model for pruning.
|
|
27
|
+
*/
|
|
28
|
+
public static register(table: string, options: Omit<PrunableModelConfig, 'table'> = {}): void {
|
|
29
|
+
PruneModelsJob.prunableModels.push({ table, ...options })
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public static async handle(): Promise<{ total: number, results: Array<{ table: string, pruned: number }> }> {
|
|
33
|
+
try {
|
|
34
|
+
log.info('Running model pruning job')
|
|
35
|
+
|
|
36
|
+
const { prunable } = await import('../../orm/src/utils/prunable')
|
|
37
|
+
|
|
38
|
+
const results: Array<{ table: string, pruned: number }> = []
|
|
39
|
+
let total = 0
|
|
40
|
+
|
|
41
|
+
for (const model of PruneModelsJob.prunableModels) {
|
|
42
|
+
const pruned = await prunable(model.table, {
|
|
43
|
+
olderThanDays: model.olderThanDays,
|
|
44
|
+
column: model.column,
|
|
45
|
+
query: model.query,
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
results.push({ table: model.table, pruned })
|
|
49
|
+
total += pruned
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
log.info(`Model pruning complete: ${total} records pruned across ${results.length} models`)
|
|
53
|
+
|
|
54
|
+
return { total, results }
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
log.error('Failed to prune models:', error)
|
|
58
|
+
throw error
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { config } from '@stacksjs/config'
|
|
2
|
+
import { log } from '@stacksjs/logging'
|
|
3
|
+
import QueryController from '../Controllers/QueryController'
|
|
4
|
+
|
|
5
|
+
export default class PruneQueryLogsJob {
|
|
6
|
+
/**
|
|
7
|
+
* Job configuration
|
|
8
|
+
*/
|
|
9
|
+
public static config = {
|
|
10
|
+
// Run the job based on the configured frequency, defaulting to daily
|
|
11
|
+
schedule: config.database?.queryLogging?.pruneFrequency
|
|
12
|
+
? `0 */${config.database.queryLogging.pruneFrequency} * * *` // Every X hours
|
|
13
|
+
: '0 0 * * *', // Daily at midnight
|
|
14
|
+
|
|
15
|
+
// Prevent overlapping job executions
|
|
16
|
+
withoutOverlapping: true,
|
|
17
|
+
|
|
18
|
+
// Timeout after 5 minutes
|
|
19
|
+
timeout: 5 * 60,
|
|
20
|
+
|
|
21
|
+
// Retry up to 3 times with exponential backoff
|
|
22
|
+
retries: 3,
|
|
23
|
+
retryAfter: [60, 120, 300], // seconds
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Execute the job
|
|
28
|
+
*/
|
|
29
|
+
public static async handle() {
|
|
30
|
+
try {
|
|
31
|
+
log.info('Running query logs pruning job')
|
|
32
|
+
|
|
33
|
+
// Skip if query logging is disabled
|
|
34
|
+
if (!config.database?.queryLogging?.enabled) {
|
|
35
|
+
log.info('Query logging is disabled, skipping pruning job')
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Prune old query logs
|
|
40
|
+
const result = await QueryController.pruneQueryLogs()
|
|
41
|
+
|
|
42
|
+
log.info(`Successfully pruned ${result.pruned} query logs older than ${result.retentionDays} days`)
|
|
43
|
+
|
|
44
|
+
return result
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
log.error('Failed to prune query logs:', error)
|
|
48
|
+
throw error
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# What are Jobs
|
|
2
|
+
|
|
3
|
+
Jobs are a way to define a task that should be executed at a specific time. They are a Stacks primitive that may be called from anywhere in your application.
|
|
4
|
+
|
|
5
|
+
> [!TIP]
|
|
6
|
+
> Jobs can also be executed on a schedule, using cron syntax. Simply define the `rate` at which the job should run, and Stacks will take care of the rest.
|
|
7
|
+
|
|
8
|
+
## Get Started
|
|
9
|
+
|
|
10
|
+
The following command will bootstrap a new job file in the `app/Jobs` directory.
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
buddy make:job ExampleJob
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
|
|
18
|
+
### Example
|
|
19
|
+
|
|
20
|
+
A simple example of a job that logs a message. _For a closer look, take a peak at the [ExampleJob.ts](./ExampleJob.ts)._
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
|
|
24
|
+
export interface JobOptions {
|
|
25
|
+
/**
|
|
26
|
+
|
|
27
|
+
_ The name of the job.
|
|
28
|
+
|
|
29
|
+
_/
|
|
30
|
+
name?: string
|
|
31
|
+
description?: string
|
|
32
|
+
handle?: string | Function
|
|
33
|
+
action?: string // the ActionName. Typed support incoming
|
|
34
|
+
timezone?: string
|
|
35
|
+
/**
|
|
36
|
+
|
|
37
|
+
_ Number of tries. Must be between 0 and 185.
|
|
38
|
+
|
|
39
|
+
_/
|
|
40
|
+
tries?: IntRange<0, 185>
|
|
41
|
+
backoff?: number | number[]
|
|
42
|
+
rate?: string | Every
|
|
43
|
+
enabled?: boolean
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const options: JobOptions = {
|
|
47
|
+
name: 'Example Job', // optional, defaults to the file name
|
|
48
|
+
description: 'A demo (cron) job that runs every minute', // optional, used in the dashboard for context
|
|
49
|
+
tries: 3, // optional, defaults to 3 retries (in case of failures)
|
|
50
|
+
backoff: 3, // optional, defaults to 3-second delays between retries
|
|
51
|
+
rate: Every.Minute, // optional, '_ _ _ _ *' in cron syntax
|
|
52
|
+
handle: () => { // action: 'SendWelcomeEmail', // instead of handle, you may target an action or `action: () => {`
|
|
53
|
+
log.info('This message logs every minute') // unless triggered via a route.job() call, in which case it logs once
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default new Job(options)
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 🚜 Contributing
|
|
62
|
+
|
|
63
|
+
Please review the [Contributing Guide](https://github.com/stacksjs/contributing) for details.
|
|
64
|
+
|
|
65
|
+
## 🏝 Community
|
|
66
|
+
|
|
67
|
+
For help, discussion about best practices, or any other conversation that would benefit from being searchable:
|
|
68
|
+
|
|
69
|
+
[Discussions on GitHub](https://github.com/stacksjs/stacks/discussions)
|
|
70
|
+
|
|
71
|
+
For casual chit-chat with others using this package:
|
|
72
|
+
|
|
73
|
+
[Join the Stacks Discord Server](https://discord.gg/stacksjs)
|
|
74
|
+
|
|
75
|
+
## 📄 License
|
|
76
|
+
|
|
77
|
+
The MIT License (MIT). Please see [LICENSE](../../LICENSE.md) for more information.
|
|
78
|
+
|
|
79
|
+
Made with 💙
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { config } from '@stacksjs/config'
|
|
2
|
+
import { mail, template } from '@stacksjs/email'
|
|
3
|
+
import { log } from '@stacksjs/logging'
|
|
4
|
+
import { buildUnsubscribeHeaders } from '@stacksjs/newsletter'
|
|
5
|
+
import { Campaign, CampaignSend, EmailList, EmailListSubscriber, Subscriber } from '@stacksjs/orm'
|
|
6
|
+
import { Job } from '@stacksjs/queue'
|
|
7
|
+
import { url } from '@stacksjs/router'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Newsletter campaign dispatcher.
|
|
11
|
+
*
|
|
12
|
+
* Loads the campaign + its target list, walks every active pivot row,
|
|
13
|
+
* renders the template, attaches per-recipient `List-Unsubscribe`
|
|
14
|
+
* headers (RFC 8058), and hands each envelope to `@stacksjs/email`.
|
|
15
|
+
*
|
|
16
|
+
* Why per-recipient sends instead of one fan-out send? The pivot
|
|
17
|
+
* UUID is the unsubscribe token — embedding it means we can't share
|
|
18
|
+
* a single envelope across recipients without leaking everyone else's
|
|
19
|
+
* unsubscribe URL via Bcc round-tripping. Per-recipient also lets us
|
|
20
|
+
* record granular CampaignSend status rows for retries and analytics.
|
|
21
|
+
*
|
|
22
|
+
* Failures from a single recipient don't poison the chunk — we record
|
|
23
|
+
* the error on the `CampaignSend` row and keep going. Whole-job
|
|
24
|
+
* failures (e.g. "campaign not found") throw so the queue retries.
|
|
25
|
+
*/
|
|
26
|
+
interface SendCampaignPayload {
|
|
27
|
+
campaignId: number
|
|
28
|
+
chunkSize?: number
|
|
29
|
+
dryRun?: boolean
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default new Job({
|
|
33
|
+
name: 'SendCampaign',
|
|
34
|
+
description: 'Fan a campaign out to its target list (background)',
|
|
35
|
+
queue: 'campaigns',
|
|
36
|
+
// Whole-campaign failures are rare; we don't want a flaky DB to
|
|
37
|
+
// double-send a marketing blast. One automatic retry, then surface.
|
|
38
|
+
tries: 2,
|
|
39
|
+
backoff: [60],
|
|
40
|
+
|
|
41
|
+
async handle(payload: SendCampaignPayload) {
|
|
42
|
+
if (!payload?.campaignId)
|
|
43
|
+
throw new Error('[SendCampaign] payload.campaignId is required')
|
|
44
|
+
|
|
45
|
+
const campaign = await (Campaign as any).find(payload.campaignId)
|
|
46
|
+
if (!campaign)
|
|
47
|
+
throw new Error(`[SendCampaign] Campaign ${payload.campaignId} not found`)
|
|
48
|
+
|
|
49
|
+
if (campaign.status === 'sent' || campaign.status === 'cancelled') {
|
|
50
|
+
log.warn(`[SendCampaign] Skipping campaign ${campaign.id} in status '${campaign.status}'`)
|
|
51
|
+
return { sent: 0, skipped: true }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!campaign.email_list_id)
|
|
55
|
+
throw new Error(`[SendCampaign] Campaign ${campaign.id} has no email_list_id`)
|
|
56
|
+
|
|
57
|
+
const list = await (EmailList as any).find(campaign.email_list_id)
|
|
58
|
+
if (!list)
|
|
59
|
+
throw new Error(`[SendCampaign] EmailList ${campaign.email_list_id} not found`)
|
|
60
|
+
|
|
61
|
+
await campaign.update({ status: 'sending' })
|
|
62
|
+
|
|
63
|
+
const appName = config.app.name || 'Stacks'
|
|
64
|
+
const fromAddress = {
|
|
65
|
+
name: campaign.from_name || config.email.from?.name || appName,
|
|
66
|
+
address: campaign.from_address || config.email.from?.address || 'no-reply@stacksjs.com',
|
|
67
|
+
}
|
|
68
|
+
const unsubscribeMailbox = (config as any)?.email?.unsubscribeMailbox
|
|
69
|
+
|
|
70
|
+
const chunkSize = payload.chunkSize ?? 50
|
|
71
|
+
const dryRun = payload.dryRun ?? false
|
|
72
|
+
|
|
73
|
+
let sent = 0
|
|
74
|
+
let failed = 0
|
|
75
|
+
let offset = 0
|
|
76
|
+
|
|
77
|
+
// Walk active pivots in chunks. We never load the full list into
|
|
78
|
+
// memory — large lists (100k+) would OOM the worker, and we want
|
|
79
|
+
// crash safety: if the worker dies mid-send we can resume from the
|
|
80
|
+
// first subscriber without a CampaignSend row for this campaign.
|
|
81
|
+
while (true) {
|
|
82
|
+
const pivots = await (EmailListSubscriber as any)
|
|
83
|
+
.where('email_list_id', campaign.email_list_id)
|
|
84
|
+
.where('status', 'subscribed')
|
|
85
|
+
.limit(chunkSize)
|
|
86
|
+
.offset(offset)
|
|
87
|
+
.get()
|
|
88
|
+
|
|
89
|
+
if (!pivots || pivots.length === 0)
|
|
90
|
+
break
|
|
91
|
+
|
|
92
|
+
for (const pivot of pivots) {
|
|
93
|
+
// Skip if we've already sent for this (campaign, subscriber).
|
|
94
|
+
// The unique index protects us, but checking up front avoids a
|
|
95
|
+
// try/catch round-trip per existing row when we resume.
|
|
96
|
+
const existing = await (CampaignSend as any)
|
|
97
|
+
.where('campaign_id', campaign.id)
|
|
98
|
+
.where('subscriber_id', pivot.subscriber_id)
|
|
99
|
+
.first()
|
|
100
|
+
if (existing && existing.status === 'sent')
|
|
101
|
+
continue
|
|
102
|
+
|
|
103
|
+
const subscriber = await (Subscriber as any).find(pivot.subscriber_id)
|
|
104
|
+
if (!subscriber || !subscriber.email)
|
|
105
|
+
continue
|
|
106
|
+
|
|
107
|
+
// The pivot UUID is the per-list unsubscribe token. Both the
|
|
108
|
+
// header and the in-body link point to the same handler so
|
|
109
|
+
// RFC 8058 one-click and "click the link" land in the same
|
|
110
|
+
// place.
|
|
111
|
+
const unsubscribeUrl = url('email.unsubscribe', { token: pivot.uuid })
|
|
112
|
+
const headers = buildUnsubscribeHeaders({
|
|
113
|
+
url: unsubscribeUrl,
|
|
114
|
+
mailto: unsubscribeMailbox,
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
let html: string
|
|
118
|
+
let text: string | undefined
|
|
119
|
+
try {
|
|
120
|
+
const rendered = await template(campaign.template, {
|
|
121
|
+
variables: {
|
|
122
|
+
email: subscriber.email,
|
|
123
|
+
unsubscribeUrl,
|
|
124
|
+
listName: list.name,
|
|
125
|
+
campaignName: campaign.name,
|
|
126
|
+
},
|
|
127
|
+
subject: campaign.subject,
|
|
128
|
+
})
|
|
129
|
+
html = rendered.html
|
|
130
|
+
text = rendered.text
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
// Template name didn't resolve to a file — fall back to
|
|
134
|
+
// treating campaign.template as raw HTML. Saves you from
|
|
135
|
+
// having to scaffold a .stx file for one-off blasts.
|
|
136
|
+
html = campaign.template
|
|
137
|
+
text = campaign.text || undefined
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const sendRow = existing
|
|
141
|
+
?? (await (CampaignSend as any).create({
|
|
142
|
+
campaign_id: campaign.id,
|
|
143
|
+
subscriber_id: pivot.subscriber_id,
|
|
144
|
+
email_list_id: campaign.email_list_id,
|
|
145
|
+
status: 'queued',
|
|
146
|
+
}))
|
|
147
|
+
|
|
148
|
+
if (dryRun) {
|
|
149
|
+
await sendRow.update({ status: 'sent', sent_at: new Date().toISOString(), provider_message_id: 'dry-run' })
|
|
150
|
+
sent++
|
|
151
|
+
continue
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const result = await mail.send({
|
|
156
|
+
to: [subscriber.email],
|
|
157
|
+
from: fromAddress,
|
|
158
|
+
subject: campaign.subject,
|
|
159
|
+
html,
|
|
160
|
+
text,
|
|
161
|
+
// `headers` is optional on EmailMessage — drivers that
|
|
162
|
+
// already propagate raw headers pick this up; ones that
|
|
163
|
+
// don't yet will silently drop and we lose only the
|
|
164
|
+
// RFC 8058 one-click affordance. The in-body link still
|
|
165
|
+
// works in every case.
|
|
166
|
+
headers,
|
|
167
|
+
} as any)
|
|
168
|
+
|
|
169
|
+
if (result?.success === false) {
|
|
170
|
+
await sendRow.update({ status: 'failed', error: result?.message ?? 'driver returned failure' })
|
|
171
|
+
failed++
|
|
172
|
+
continue
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
await sendRow.update({
|
|
176
|
+
status: 'sent',
|
|
177
|
+
sent_at: new Date().toISOString(),
|
|
178
|
+
provider_message_id: result?.messageId ?? null,
|
|
179
|
+
})
|
|
180
|
+
sent++
|
|
181
|
+
}
|
|
182
|
+
catch (err: unknown) {
|
|
183
|
+
const message = err instanceof Error ? err.message : String(err)
|
|
184
|
+
await sendRow.update({ status: 'failed', error: message })
|
|
185
|
+
failed++
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
offset += pivots.length
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
await campaign.update({
|
|
193
|
+
status: 'sent',
|
|
194
|
+
sent_at: new Date().toISOString(),
|
|
195
|
+
sent_count: sent,
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
log.debug(`[SendCampaign] campaign=${campaign.id} sent=${sent} failed=${failed}`)
|
|
199
|
+
return { sent, failed }
|
|
200
|
+
},
|
|
201
|
+
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { EmailMessage } from '@stacksjs/types'
|
|
2
|
+
import { mail } from '@stacksjs/email'
|
|
3
|
+
import { log } from '@stacksjs/logging'
|
|
4
|
+
import { Job } from '@stacksjs/queue'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Background email-send job.
|
|
8
|
+
*
|
|
9
|
+
* `mail.queue(message)` (and `.later(seconds, message)` / `.queueOn(queue, message)`)
|
|
10
|
+
* dispatch to a job named `SendEmail` — this is its handler. Without this
|
|
11
|
+
* file the queued envelope just sat in the `jobs` table forever (the
|
|
12
|
+
* framework had no shipped handler), so any caller using `mail.queue()`
|
|
13
|
+
* silently dropped the email.
|
|
14
|
+
*
|
|
15
|
+
* Uses `mail.use(driver)` so the same payload can be sent through any
|
|
16
|
+
* registered transport — preserves the driver the producer chose at
|
|
17
|
+
* dispatch time even if the worker process inherits a different default.
|
|
18
|
+
*/
|
|
19
|
+
interface SendEmailPayload {
|
|
20
|
+
message: EmailMessage
|
|
21
|
+
driver?: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default new Job({
|
|
25
|
+
name: 'SendEmail',
|
|
26
|
+
description: 'Send an email via the configured transport (background)',
|
|
27
|
+
queue: 'emails',
|
|
28
|
+
tries: 3,
|
|
29
|
+
backoff: [10, 30, 60], // 10s → 30s → 60s
|
|
30
|
+
|
|
31
|
+
async handle(payload: SendEmailPayload) {
|
|
32
|
+
if (!payload?.message) {
|
|
33
|
+
throw new Error('[SendEmail] payload.message is required')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const transport = payload.driver
|
|
37
|
+
? mail.use(payload.driver)
|
|
38
|
+
: mail
|
|
39
|
+
|
|
40
|
+
const result = await transport.send(payload.message)
|
|
41
|
+
|
|
42
|
+
if (!result?.success) {
|
|
43
|
+
// Re-throw so the worker counts this as a failed attempt (and the
|
|
44
|
+
// queue retries with the configured backoff). Without throwing,
|
|
45
|
+
// failed sends would silently drop on the floor.
|
|
46
|
+
throw new Error(`[SendEmail] driver '${result?.provider ?? payload.driver ?? 'default'}' returned failure: ${result?.message ?? 'unknown error'}`)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
log.debug(`[SendEmail] sent via ${result.provider} (messageId=${result.messageId ?? 'n/a'})`)
|
|
50
|
+
return { messageId: result.messageId, provider: result.provider }
|
|
51
|
+
},
|
|
52
|
+
})
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Job } from '@stacksjs/queue'
|
|
2
|
+
import { passwordResets } from '@stacksjs/auth'
|
|
3
|
+
|
|
4
|
+
interface PasswordResetPayload {
|
|
5
|
+
email: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
console.log('[SendPasswordResetEmailJob] Job file loaded')
|
|
9
|
+
|
|
10
|
+
export default new Job({
|
|
11
|
+
name: 'SendPasswordResetEmail',
|
|
12
|
+
description: 'Sends a password reset email to the user',
|
|
13
|
+
queue: 'emails',
|
|
14
|
+
tries: 3,
|
|
15
|
+
backoff: [10, 30, 60], // Retry after 10s, 30s, 60s
|
|
16
|
+
|
|
17
|
+
async handle(payload: PasswordResetPayload) {
|
|
18
|
+
console.log('[Job.handle] SendPasswordResetEmailJob.handle() called')
|
|
19
|
+
console.log('[Job.handle] Received payload:', payload)
|
|
20
|
+
|
|
21
|
+
const { email } = payload
|
|
22
|
+
|
|
23
|
+
if (!email) {
|
|
24
|
+
console.error('[Job.handle] No email in payload!')
|
|
25
|
+
throw new Error('Email is required to send password reset')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
console.log(`[Job.handle] Processing password reset for: ${email}`)
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
console.log('[Job.handle] Calling passwordResets().sendEmail()...')
|
|
32
|
+
const resetInstance = passwordResets(email)
|
|
33
|
+
console.log('[Job.handle] Password reset instance created')
|
|
34
|
+
|
|
35
|
+
await resetInstance.sendEmail()
|
|
36
|
+
console.log(`[Job.handle] Email sent successfully to ${email}`)
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error(`[Job.handle] Failed to send email to ${email}`)
|
|
40
|
+
console.error('[Job.handle] Error:', error)
|
|
41
|
+
throw error // Re-throw to trigger retry
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
})
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { log } from '@stacksjs/logging'
|
|
2
|
+
import { Job } from '@stacksjs/queue'
|
|
3
|
+
import { useSearchEngine } from '@stacksjs/search-engine'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Background search-index sync job (stacksjs/stacks#1891).
|
|
7
|
+
*
|
|
8
|
+
* Models declaring `traits.useSearch: { queueable: true }` dispatch
|
|
9
|
+
* to this job from their `afterCreate` / `afterUpdate` / `afterDelete`
|
|
10
|
+
* hooks instead of calling the search-engine driver inline. That
|
|
11
|
+
* keeps the request path off the network round-trip when the search
|
|
12
|
+
* backend is on a different host — slow upserts or transient
|
|
13
|
+
* Meilisearch failures don't block the user write.
|
|
14
|
+
*
|
|
15
|
+
* Payload shape (dispatched by `define-model.ts:buildSearchHooks`):
|
|
16
|
+
* - `{ op: 'upsert', index, doc }` — create or update a document
|
|
17
|
+
* - `{ op: 'delete', index, id }` — remove a document by id
|
|
18
|
+
*
|
|
19
|
+
* Failures throw so the queue counts them as failed attempts and
|
|
20
|
+
* the configured backoff retries. With `tries: 5` and the default
|
|
21
|
+
* backoff, a five-minute Meilisearch outage doesn't lose writes.
|
|
22
|
+
*/
|
|
23
|
+
interface SyncSearchIndexPayload {
|
|
24
|
+
index: string
|
|
25
|
+
op: 'upsert' | 'delete'
|
|
26
|
+
doc?: Record<string, unknown>
|
|
27
|
+
id?: number
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default new Job({
|
|
31
|
+
name: 'SyncSearchIndex',
|
|
32
|
+
description: 'Sync a model write to the search engine (background)',
|
|
33
|
+
queue: 'search',
|
|
34
|
+
tries: 5,
|
|
35
|
+
backoff: [5, 15, 30, 60, 120],
|
|
36
|
+
|
|
37
|
+
async handle(payload: SyncSearchIndexPayload) {
|
|
38
|
+
if (!payload?.index || !payload?.op) {
|
|
39
|
+
throw new Error('[SyncSearchIndex] payload.index and payload.op are required')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const engine = useSearchEngine()
|
|
43
|
+
|
|
44
|
+
if (payload.op === 'upsert') {
|
|
45
|
+
if (!payload.doc) {
|
|
46
|
+
throw new Error('[SyncSearchIndex] upsert requires payload.doc')
|
|
47
|
+
}
|
|
48
|
+
await engine.addDocument(payload.index, payload.doc)
|
|
49
|
+
log.debug(`[SyncSearchIndex] upserted into ${payload.index}`)
|
|
50
|
+
return { ok: true, op: 'upsert', index: payload.index }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (payload.op === 'delete') {
|
|
54
|
+
if (payload.id == null) {
|
|
55
|
+
throw new Error('[SyncSearchIndex] delete requires payload.id')
|
|
56
|
+
}
|
|
57
|
+
await engine.deleteDocument(payload.index, Number(payload.id))
|
|
58
|
+
log.debug(`[SyncSearchIndex] deleted ${payload.id} from ${payload.index}`)
|
|
59
|
+
return { ok: true, op: 'delete', index: payload.index, id: payload.id }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
throw new Error(`[SyncSearchIndex] unknown op '${(payload as { op?: string }).op}'`)
|
|
63
|
+
},
|
|
64
|
+
})
|
package/app/Listener.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { StacksEvents, WildcardHandler } from '@stacksjs/events'
|
|
2
|
+
import { handleError } from '@stacksjs/error-handling'
|
|
3
|
+
import { emitter } from '@stacksjs/events'
|
|
4
|
+
import { path as p } from '@stacksjs/path'
|
|
5
|
+
import events from './Events'
|
|
6
|
+
|
|
7
|
+
// Cache resolved action modules to avoid repeated dynamic imports
|
|
8
|
+
const actionCache = new Map<string, { handle: (event: any) => Promise<any> | any }>()
|
|
9
|
+
|
|
10
|
+
// Deduplicate in-flight imports to prevent concurrent import races
|
|
11
|
+
const pendingImports = new Map<string, Promise<{ handle: (event: any) => Promise<any> | any } | null>>()
|
|
12
|
+
|
|
13
|
+
// Pre-compute which event types have listeners for O(1) lookup
|
|
14
|
+
const eventTypes = new Set(Object.keys(events))
|
|
15
|
+
|
|
16
|
+
export async function handleEvents() {
|
|
17
|
+
emitter.on('*', listenEvents as WildcardHandler<StacksEvents>)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function listenEvents(type: keyof typeof events, event: any) {
|
|
21
|
+
// Fast path: skip events with no registered listeners
|
|
22
|
+
if (!eventTypes.has(type as string))
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
const eventListeners = events[type]
|
|
26
|
+
if (!eventListeners || eventListeners.length === 0)
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
// Fire-and-forget with error handling — mitt doesn't await wildcard handlers
|
|
30
|
+
processListeners(type as string, eventListeners, event)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function resolveAction(listener: string): Promise<{ handle: (event: any) => Promise<any> | any } | null> {
|
|
34
|
+
// Check cache first
|
|
35
|
+
const cached = actionCache.get(listener)
|
|
36
|
+
if (cached) return cached
|
|
37
|
+
|
|
38
|
+
// Check if an import is already in-flight
|
|
39
|
+
let pending = pendingImports.get(listener)
|
|
40
|
+
if (pending) return pending
|
|
41
|
+
|
|
42
|
+
// Start the import and cache the promise to deduplicate concurrent calls
|
|
43
|
+
pending = (async () => {
|
|
44
|
+
try {
|
|
45
|
+
const imported = await import(p.appPath(`Actions/${listener}.ts`))
|
|
46
|
+
const actionModule = imported.default
|
|
47
|
+
if (actionModule && typeof actionModule.handle === 'function') {
|
|
48
|
+
actionCache.set(listener, actionModule)
|
|
49
|
+
return actionModule
|
|
50
|
+
}
|
|
51
|
+
handleError(`Action "${listener}" does not export a handle method`)
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
handleError(`Failed to import action "${listener}"`, error)
|
|
56
|
+
return null
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
pendingImports.delete(listener)
|
|
60
|
+
}
|
|
61
|
+
})()
|
|
62
|
+
|
|
63
|
+
pendingImports.set(listener, pending)
|
|
64
|
+
return pending
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function processListeners(type: string, listeners: string[], event: any) {
|
|
68
|
+
for (const listener of listeners) {
|
|
69
|
+
try {
|
|
70
|
+
if (typeof listener === 'function') {
|
|
71
|
+
await (listener as any)(event)
|
|
72
|
+
continue
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const action = await resolveAction(listener)
|
|
76
|
+
if (action) {
|
|
77
|
+
await action.handle(event)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
handleError(`Failed to execute listener "${listener}" for event "${type}"`, error)
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CLI } from '@stacksjs/types'
|
|
2
|
+
import process from 'node:process'
|
|
3
|
+
|
|
4
|
+
export default function (cli: CLI) {
|
|
5
|
+
// Listen to the `inspire:three` command
|
|
6
|
+
cli.on('inspire:three', () => {
|
|
7
|
+
// eslint-disable-next-line no-console
|
|
8
|
+
console.log('inspiring with three quotes')
|
|
9
|
+
// Do something
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
// Listen to the default command
|
|
13
|
+
cli.on('inspire:!', () => {
|
|
14
|
+
// Do something
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// Listen to unknown commands
|
|
18
|
+
cli.on('inspire:*', () => {
|
|
19
|
+
console.error('Invalid command: %s', cli.args.join(' '))
|
|
20
|
+
process.exit(1)
|
|
21
|
+
})
|
|
22
|
+
}
|