@stacksjs/defaults 0.70.58 → 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 { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `DELETE /api/dashboard/kanban/boards/:id` (stacksjs/stacks#1846 Phase 2).
|
|
6
|
+
*
|
|
7
|
+
* Hard delete with cascade: removes the board, its columns, its cards,
|
|
8
|
+
* its labels, and the relevant pivot rows in `card_labels` and
|
|
9
|
+
* `card_assignees`. No DB-level FK cascade to lean on — the existing
|
|
10
|
+
* Stacks migration convention is app-layer integrity, so the cascade
|
|
11
|
+
* lives in this action.
|
|
12
|
+
*
|
|
13
|
+
* Order matters: pivots first (they reference card_id), then cards,
|
|
14
|
+
* then columns, then labels, then the board itself. Reverse-of-FK
|
|
15
|
+
* order so no statement runs against rows that still have referents.
|
|
16
|
+
*
|
|
17
|
+
* Soft-archive is a different operation — call PATCH with
|
|
18
|
+
* `{ archived: true }`. This action is the hard delete; data is gone.
|
|
19
|
+
*/
|
|
20
|
+
export default new Action({
|
|
21
|
+
name: 'Kanban Board Destroy',
|
|
22
|
+
description: 'Hard-deletes a board and all of its columns, cards, labels, and pivot rows.',
|
|
23
|
+
method: 'DELETE',
|
|
24
|
+
apiResponse: true,
|
|
25
|
+
async handle(request) {
|
|
26
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
27
|
+
const id = Number(rawId)
|
|
28
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
29
|
+
return { error: 'Invalid board id', status: 400 }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
// Wrap in a transaction so partial failures roll back. If the
|
|
34
|
+
// active dialect doesn't support transactions through
|
|
35
|
+
// `db.transaction` (some shapes pass through to the underlying
|
|
36
|
+
// bun-query-builder which has driver-specific implementations),
|
|
37
|
+
// fall through to a best-effort sequential delete — the deletes
|
|
38
|
+
// are idempotent, so re-running the same DELETE on the same id
|
|
39
|
+
// is safe.
|
|
40
|
+
const txOps = async (qb: any) => {
|
|
41
|
+
// Pivots + card-scoped children first — they reference cards.
|
|
42
|
+
await qb.unsafe(
|
|
43
|
+
'DELETE FROM card_labels WHERE card_id IN (SELECT id FROM cards WHERE board_id = ?)',
|
|
44
|
+
[id],
|
|
45
|
+
).execute()
|
|
46
|
+
await qb.unsafe(
|
|
47
|
+
'DELETE FROM card_assignees WHERE card_id IN (SELECT id FROM cards WHERE board_id = ?)',
|
|
48
|
+
[id],
|
|
49
|
+
).execute()
|
|
50
|
+
// Card comments (Phase 3, migration 0000000112). Same
|
|
51
|
+
// card-scoped pattern as the pivots.
|
|
52
|
+
await qb.unsafe(
|
|
53
|
+
'DELETE FROM card_comments WHERE card_id IN (SELECT id FROM cards WHERE board_id = ?)',
|
|
54
|
+
[id],
|
|
55
|
+
).execute()
|
|
56
|
+
// Cards (denormalised board_id avoids the column join).
|
|
57
|
+
await qb.deleteFrom('cards').where('board_id', '=', id).execute()
|
|
58
|
+
// Columns + labels — both directly reference board_id.
|
|
59
|
+
await qb.deleteFrom('board_columns').where('board_id', '=', id).execute()
|
|
60
|
+
await qb.deleteFrom('labels').where('board_id', '=', id).execute()
|
|
61
|
+
// Finally the board itself.
|
|
62
|
+
await qb.deleteFrom('boards').where('id', '=', id).execute()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
await (db as any).transaction(txOps)
|
|
67
|
+
}
|
|
68
|
+
catch (txErr) {
|
|
69
|
+
// Transaction unavailable or driver-specific shape failed —
|
|
70
|
+
// run sequentially. If this fails mid-way the next call to
|
|
71
|
+
// the same action will pick up where the previous one left
|
|
72
|
+
// off (all deletes are idempotent).
|
|
73
|
+
console.warn('[dashboard/kanban] BoardDestroyAction transaction unavailable, falling back to sequential:', txErr)
|
|
74
|
+
await txOps(db)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return { deleted: true, id }
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
console.error('[dashboard/kanban] BoardDestroyAction failed:', err)
|
|
81
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
})
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface BoardRow {
|
|
5
|
+
id: number
|
|
6
|
+
uuid: string | null
|
|
7
|
+
name: string
|
|
8
|
+
description: string | null
|
|
9
|
+
icon: string
|
|
10
|
+
color: string
|
|
11
|
+
position: number
|
|
12
|
+
archived: number
|
|
13
|
+
created_at: string | null
|
|
14
|
+
updated_at: string | null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ColumnRow {
|
|
18
|
+
id: number
|
|
19
|
+
uuid: string | null
|
|
20
|
+
board_id: number
|
|
21
|
+
name: string
|
|
22
|
+
position: number
|
|
23
|
+
card_limit: number | null
|
|
24
|
+
color: string
|
|
25
|
+
created_at: string | null
|
|
26
|
+
updated_at: string | null
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface CardRow {
|
|
30
|
+
id: number
|
|
31
|
+
uuid: string | null
|
|
32
|
+
column_id: number
|
|
33
|
+
board_id: number
|
|
34
|
+
title: string
|
|
35
|
+
description: string | null
|
|
36
|
+
position: number
|
|
37
|
+
created_by_user_id: number | null
|
|
38
|
+
due_date: string | null
|
|
39
|
+
archived: number
|
|
40
|
+
created_at: string | null
|
|
41
|
+
updated_at: string | null
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface LabelRow {
|
|
45
|
+
id: number
|
|
46
|
+
board_id: number
|
|
47
|
+
name: string
|
|
48
|
+
color: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* `GET /api/dashboard/kanban/boards/:id`
|
|
53
|
+
*
|
|
54
|
+
* Returns a single board with its columns + cards + label palette
|
|
55
|
+
* nested in render order. Powers the kanban board page
|
|
56
|
+
* (`/kanban/[id]`) — Phase 2 hits this on mount, the drag handler
|
|
57
|
+
* then mutates positions via the (Phase 2) reorder endpoint and
|
|
58
|
+
* relies on optimistic updates for snappy UX.
|
|
59
|
+
*
|
|
60
|
+
* Query layout (3 queries, all indexed):
|
|
61
|
+
* 1. Single-row board lookup by id.
|
|
62
|
+
* 2. All columns for the board (ordered by `position`).
|
|
63
|
+
* 3. All non-archived cards for the board (ordered by
|
|
64
|
+
* `column_id, position`).
|
|
65
|
+
* 4. All labels for the board.
|
|
66
|
+
*
|
|
67
|
+
* Card-label pivot reads land in Phase 3 alongside the card detail
|
|
68
|
+
* modal — the board view shows label chips inline, hydrated from a
|
|
69
|
+
* single pivot query batched with the card fetch.
|
|
70
|
+
*/
|
|
71
|
+
export default new Action({
|
|
72
|
+
name: 'Kanban Board Show',
|
|
73
|
+
description: 'Returns a single kanban board with its columns + cards + label palette.',
|
|
74
|
+
method: 'GET',
|
|
75
|
+
apiResponse: true,
|
|
76
|
+
async handle(request) {
|
|
77
|
+
// Route param resolution: bun-router exposes `:id` via
|
|
78
|
+
// `request.param('id')` / `request.params.id`. Both shapes appear
|
|
79
|
+
// in this codebase depending on how the route was registered;
|
|
80
|
+
// covering both keeps the action portable.
|
|
81
|
+
const rawId = (request as any)?.params?.id
|
|
82
|
+
?? (request as any)?.param?.('id')
|
|
83
|
+
?? null
|
|
84
|
+
const id = Number(rawId)
|
|
85
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
86
|
+
return { error: 'Invalid board id', status: 400 }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const boards = await db.unsafe(
|
|
91
|
+
'SELECT * FROM boards WHERE id = ? LIMIT 1',
|
|
92
|
+
[id],
|
|
93
|
+
).execute() as BoardRow[]
|
|
94
|
+
const board = boards[0]
|
|
95
|
+
if (!board) {
|
|
96
|
+
return { error: 'Board not found', status: 404 }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const [columns, cards, labels] = await Promise.all([
|
|
100
|
+
db.unsafe(
|
|
101
|
+
'SELECT * FROM board_columns WHERE board_id = ? ORDER BY position ASC, id ASC',
|
|
102
|
+
[id],
|
|
103
|
+
).execute() as Promise<ColumnRow[]>,
|
|
104
|
+
db.unsafe(
|
|
105
|
+
'SELECT * FROM cards WHERE board_id = ? AND archived = 0 ORDER BY column_id ASC, position ASC, id ASC',
|
|
106
|
+
[id],
|
|
107
|
+
).execute() as Promise<CardRow[]>,
|
|
108
|
+
db.unsafe(
|
|
109
|
+
'SELECT id, board_id, name, color FROM labels WHERE board_id = ? ORDER BY name ASC',
|
|
110
|
+
[id],
|
|
111
|
+
).execute() as Promise<LabelRow[]>,
|
|
112
|
+
])
|
|
113
|
+
|
|
114
|
+
// Pivot lookups for label + assignee chips on card previews
|
|
115
|
+
// (stacksjs/stacks#1846 Phase 3). Two batched JOINs keyed off the
|
|
116
|
+
// board's card list — single round-trip per pivot, then group
|
|
117
|
+
// client-side into `cardId → list` maps.
|
|
118
|
+
const [cardLabelRows, cardAssigneeRows] = await Promise.all([
|
|
119
|
+
db.unsafe(
|
|
120
|
+
`SELECT cl.card_id, l.id, l.name, l.color
|
|
121
|
+
FROM card_labels cl
|
|
122
|
+
JOIN labels l ON l.id = cl.label_id
|
|
123
|
+
WHERE cl.card_id IN (SELECT id FROM cards WHERE board_id = ? AND archived = 0)
|
|
124
|
+
ORDER BY l.name ASC`,
|
|
125
|
+
[id],
|
|
126
|
+
).execute() as Promise<Array<{ card_id: number, id: number, name: string, color: string }>>,
|
|
127
|
+
db.unsafe(
|
|
128
|
+
`SELECT ca.card_id, ca.user_id, u.name, u.email
|
|
129
|
+
FROM card_assignees ca
|
|
130
|
+
LEFT JOIN users u ON u.id = ca.user_id
|
|
131
|
+
WHERE ca.card_id IN (SELECT id FROM cards WHERE board_id = ? AND archived = 0)`,
|
|
132
|
+
[id],
|
|
133
|
+
).execute() as Promise<Array<{ card_id: number, user_id: number, name: string | null, email: string | null }>>,
|
|
134
|
+
])
|
|
135
|
+
|
|
136
|
+
const labelsByCard = new Map<number, Array<{ id: number, name: string, color: string }>>()
|
|
137
|
+
for (const r of cardLabelRows ?? []) {
|
|
138
|
+
const list = labelsByCard.get(r.card_id) ?? []
|
|
139
|
+
list.push({ id: r.id, name: r.name, color: r.color })
|
|
140
|
+
labelsByCard.set(r.card_id, list)
|
|
141
|
+
}
|
|
142
|
+
const assigneesByCard = new Map<number, Array<{ userId: number, name: string | null, email: string | null }>>()
|
|
143
|
+
for (const r of cardAssigneeRows ?? []) {
|
|
144
|
+
const list = assigneesByCard.get(r.card_id) ?? []
|
|
145
|
+
list.push({ userId: r.user_id, name: r.name, email: r.email })
|
|
146
|
+
assigneesByCard.set(r.card_id, list)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Group cards by column id so the page renders columns directly
|
|
150
|
+
// from `columns[].cards` without doing the grouping client-side.
|
|
151
|
+
// Empty columns get an empty array, not undefined.
|
|
152
|
+
const cardsByColumn = new Map<number, CardRow[]>()
|
|
153
|
+
for (const c of cards ?? []) {
|
|
154
|
+
const list = cardsByColumn.get(c.column_id) ?? []
|
|
155
|
+
list.push(c)
|
|
156
|
+
cardsByColumn.set(c.column_id, list)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const responseColumns = (columns ?? []).map(col => ({
|
|
160
|
+
id: col.id,
|
|
161
|
+
uuid: col.uuid,
|
|
162
|
+
boardId: col.board_id,
|
|
163
|
+
name: col.name,
|
|
164
|
+
position: col.position,
|
|
165
|
+
cardLimit: col.card_limit,
|
|
166
|
+
color: col.color,
|
|
167
|
+
cards: (cardsByColumn.get(col.id) ?? []).map(c => ({
|
|
168
|
+
id: c.id,
|
|
169
|
+
uuid: c.uuid,
|
|
170
|
+
columnId: c.column_id,
|
|
171
|
+
boardId: c.board_id,
|
|
172
|
+
title: c.title,
|
|
173
|
+
description: c.description,
|
|
174
|
+
position: c.position,
|
|
175
|
+
createdByUserId: c.created_by_user_id,
|
|
176
|
+
dueDate: c.due_date,
|
|
177
|
+
archived: c.archived === 1,
|
|
178
|
+
createdAt: c.created_at,
|
|
179
|
+
updatedAt: c.updated_at,
|
|
180
|
+
labels: labelsByCard.get(c.id) ?? [],
|
|
181
|
+
assignees: assigneesByCard.get(c.id) ?? [],
|
|
182
|
+
})),
|
|
183
|
+
}))
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
board: {
|
|
187
|
+
id: board.id,
|
|
188
|
+
uuid: board.uuid,
|
|
189
|
+
name: board.name,
|
|
190
|
+
description: board.description,
|
|
191
|
+
icon: board.icon,
|
|
192
|
+
color: board.color,
|
|
193
|
+
position: board.position,
|
|
194
|
+
archived: board.archived === 1,
|
|
195
|
+
createdAt: board.created_at,
|
|
196
|
+
updatedAt: board.updated_at,
|
|
197
|
+
},
|
|
198
|
+
columns: responseColumns,
|
|
199
|
+
labels: (labels ?? []).map(l => ({
|
|
200
|
+
id: l.id,
|
|
201
|
+
boardId: l.board_id,
|
|
202
|
+
name: l.name,
|
|
203
|
+
color: l.color,
|
|
204
|
+
})),
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
console.error('[dashboard/kanban] BoardShowAction failed:', err)
|
|
209
|
+
return {
|
|
210
|
+
error: err instanceof Error ? err.message : 'unknown error',
|
|
211
|
+
status: 500,
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
})
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface BoardInput {
|
|
5
|
+
name?: unknown
|
|
6
|
+
description?: unknown
|
|
7
|
+
icon?: unknown
|
|
8
|
+
color?: unknown
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `POST /api/dashboard/kanban/boards` (stacksjs/stacks#1846 Phase 2).
|
|
13
|
+
*
|
|
14
|
+
* Creates a new board with sensible defaults and appends it to the
|
|
15
|
+
* end of the boards list (`position = max(position) + 1` so the new
|
|
16
|
+
* row shows up last in the index). Returns the inserted row including
|
|
17
|
+
* its id so the optimistic-insert in the dashboard store can swap its
|
|
18
|
+
* temp placeholder for the real record.
|
|
19
|
+
*
|
|
20
|
+
* Validation: title required + length-bounded; everything else is
|
|
21
|
+
* optional with model-level defaults. The validation rules on the
|
|
22
|
+
* `Board` model define the canonical contract; this action mirrors
|
|
23
|
+
* the must-have subset so a malformed body doesn't reach `db`.
|
|
24
|
+
*/
|
|
25
|
+
export default new Action({
|
|
26
|
+
name: 'Kanban Board Store',
|
|
27
|
+
description: 'Creates a new kanban board.',
|
|
28
|
+
method: 'POST',
|
|
29
|
+
apiResponse: true,
|
|
30
|
+
async handle(request) {
|
|
31
|
+
const body = (request as any).jsonBody as BoardInput | undefined ?? {}
|
|
32
|
+
|
|
33
|
+
const name = typeof body.name === 'string' ? body.name.trim() : ''
|
|
34
|
+
if (!name || name.length > 120) {
|
|
35
|
+
return { error: 'Name is required and must be 1-120 characters.', status: 400 }
|
|
36
|
+
}
|
|
37
|
+
const description = typeof body.description === 'string' ? body.description.trim() : null
|
|
38
|
+
const icon = typeof body.icon === 'string' && body.icon ? body.icon : 'rectangle.stack.fill'
|
|
39
|
+
const color = typeof body.color === 'string' && body.color ? body.color : 'violet'
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
// Position assignment: append at the end of the boards list.
|
|
43
|
+
// Concurrent inserts could pick the same `position` (race between
|
|
44
|
+
// the SELECT max() and the INSERT), but it's harmless — `position`
|
|
45
|
+
// is a sort hint, not a unique key. Reorder via /boards/reorder
|
|
46
|
+
// restores tight ordering when the user cares.
|
|
47
|
+
const maxRow = await db.unsafe(
|
|
48
|
+
'SELECT COALESCE(MAX(position), -1) AS m FROM boards WHERE archived = 0',
|
|
49
|
+
).execute() as Array<{ m: number }>
|
|
50
|
+
const nextPosition = (Number(maxRow?.[0]?.m ?? -1) + 1) || 0
|
|
51
|
+
|
|
52
|
+
await db.insertInto('boards').values({
|
|
53
|
+
name,
|
|
54
|
+
description,
|
|
55
|
+
icon,
|
|
56
|
+
color,
|
|
57
|
+
position: nextPosition,
|
|
58
|
+
archived: 0,
|
|
59
|
+
}).execute()
|
|
60
|
+
|
|
61
|
+
// SELECT the inserted row back. MySQL doesn't support RETURNING,
|
|
62
|
+
// so we use the (name, position) pair as a best-effort identifier
|
|
63
|
+
// — append-only with a unique position keeps this reliable.
|
|
64
|
+
const inserted = await db.unsafe(
|
|
65
|
+
`SELECT id, uuid, name, description, icon, color, position, archived, created_at, updated_at
|
|
66
|
+
FROM boards
|
|
67
|
+
WHERE name = ? AND position = ?
|
|
68
|
+
ORDER BY id DESC
|
|
69
|
+
LIMIT 1`,
|
|
70
|
+
[name, nextPosition],
|
|
71
|
+
).execute() as Array<{ id: number, uuid: string | null, name: string, description: string | null, icon: string, color: string, position: number, archived: number, created_at: string | null, updated_at: string | null }>
|
|
72
|
+
const row = inserted?.[0]
|
|
73
|
+
if (!row) {
|
|
74
|
+
return { error: 'Board insert succeeded but follow-up read returned nothing.', status: 500 }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
board: {
|
|
79
|
+
id: row.id,
|
|
80
|
+
uuid: row.uuid,
|
|
81
|
+
name: row.name,
|
|
82
|
+
description: row.description,
|
|
83
|
+
icon: row.icon,
|
|
84
|
+
color: row.color,
|
|
85
|
+
position: row.position,
|
|
86
|
+
archived: row.archived === 1,
|
|
87
|
+
cardCount: 0,
|
|
88
|
+
createdAt: row.created_at,
|
|
89
|
+
updatedAt: row.updated_at,
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
console.error('[dashboard/kanban] BoardStoreAction failed:', err)
|
|
95
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
})
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface BoardInput {
|
|
5
|
+
name?: unknown
|
|
6
|
+
description?: unknown
|
|
7
|
+
icon?: unknown
|
|
8
|
+
color?: unknown
|
|
9
|
+
archived?: unknown
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* `PATCH /api/dashboard/kanban/boards/:id` (stacksjs/stacks#1846 Phase 2).
|
|
14
|
+
*
|
|
15
|
+
* Partial update — only the fields present in the body are written.
|
|
16
|
+
* Omitting `archived` does NOT change the archive flag; passing
|
|
17
|
+
* `archived: true` soft-archives the board (it drops out of the
|
|
18
|
+
* /boards index but stays queryable at `/boards/:id`).
|
|
19
|
+
*
|
|
20
|
+
* `position` is intentionally NOT updatable here — bulk reordering
|
|
21
|
+
* goes through `/boards/reorder` so the page can rewrite multiple
|
|
22
|
+
* rows in one round-trip and avoid the gaps that single-row updates
|
|
23
|
+
* leave behind. Position-via-PATCH would invite the "drag a card,
|
|
24
|
+
* then the sibling row's position is wrong" footgun.
|
|
25
|
+
*/
|
|
26
|
+
export default new Action({
|
|
27
|
+
name: 'Kanban Board Update',
|
|
28
|
+
description: 'Partial update of a kanban board.',
|
|
29
|
+
method: 'PATCH',
|
|
30
|
+
apiResponse: true,
|
|
31
|
+
async handle(request) {
|
|
32
|
+
const rawId = (request as any)?.params?.id ?? (request as any)?.param?.('id') ?? null
|
|
33
|
+
const id = Number(rawId)
|
|
34
|
+
if (!Number.isFinite(id) || id <= 0) {
|
|
35
|
+
return { error: 'Invalid board id', status: 400 }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const body = (request as any).jsonBody as BoardInput | undefined ?? {}
|
|
39
|
+
const set: Record<string, unknown> = {}
|
|
40
|
+
|
|
41
|
+
if (typeof body.name === 'string') {
|
|
42
|
+
const name = body.name.trim()
|
|
43
|
+
if (!name || name.length > 120) {
|
|
44
|
+
return { error: 'Name must be 1-120 characters.', status: 400 }
|
|
45
|
+
}
|
|
46
|
+
set.name = name
|
|
47
|
+
}
|
|
48
|
+
if (typeof body.description === 'string' || body.description === null) {
|
|
49
|
+
set.description = typeof body.description === 'string' ? body.description.trim() : null
|
|
50
|
+
}
|
|
51
|
+
if (typeof body.icon === 'string' && body.icon)
|
|
52
|
+
set.icon = body.icon
|
|
53
|
+
if (typeof body.color === 'string' && body.color)
|
|
54
|
+
set.color = body.color
|
|
55
|
+
if (typeof body.archived === 'boolean')
|
|
56
|
+
set.archived = body.archived ? 1 : 0
|
|
57
|
+
|
|
58
|
+
if (Object.keys(set).length === 0) {
|
|
59
|
+
return { error: 'No updatable fields provided.', status: 400 }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
// The `db.updateTable` chain works across dialects; we accumulate
|
|
64
|
+
// the partial set above and apply it in one statement.
|
|
65
|
+
await db.updateTable('boards').set(set as any).where('id', '=', id).execute()
|
|
66
|
+
|
|
67
|
+
const rows = await db.unsafe(
|
|
68
|
+
`SELECT id, uuid, name, description, icon, color, position, archived, created_at, updated_at
|
|
69
|
+
FROM boards WHERE id = ? LIMIT 1`,
|
|
70
|
+
[id],
|
|
71
|
+
).execute() as Array<Record<string, unknown>>
|
|
72
|
+
const r = rows?.[0]
|
|
73
|
+
if (!r) {
|
|
74
|
+
return { error: 'Board not found', status: 404 }
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
board: {
|
|
78
|
+
id: Number(r.id),
|
|
79
|
+
uuid: r.uuid == null ? null : String(r.uuid),
|
|
80
|
+
name: String(r.name),
|
|
81
|
+
description: r.description == null ? null : String(r.description),
|
|
82
|
+
icon: String(r.icon),
|
|
83
|
+
color: String(r.color),
|
|
84
|
+
position: Number(r.position),
|
|
85
|
+
archived: Number(r.archived) === 1,
|
|
86
|
+
createdAt: r.created_at == null ? null : String(r.created_at),
|
|
87
|
+
updatedAt: r.updated_at == null ? null : String(r.updated_at),
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
console.error('[dashboard/kanban] BoardUpdateAction failed:', err)
|
|
93
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
})
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface BoardRow {
|
|
5
|
+
id: number
|
|
6
|
+
uuid: string | null
|
|
7
|
+
name: string
|
|
8
|
+
description: string | null
|
|
9
|
+
icon: string
|
|
10
|
+
color: string
|
|
11
|
+
position: number
|
|
12
|
+
archived: number
|
|
13
|
+
created_at: string | null
|
|
14
|
+
updated_at: string | null
|
|
15
|
+
card_count?: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* `GET /api/dashboard/kanban/boards`
|
|
20
|
+
*
|
|
21
|
+
* Lists every non-archived board with a fast card-count sub-query so
|
|
22
|
+
* the index page can show "5 cards" badges without a second round-trip
|
|
23
|
+
* per board. Cards table is joined in aggregate, not row-by-row, so
|
|
24
|
+
* the response stays single-query (N+1 free).
|
|
25
|
+
*
|
|
26
|
+
* Auth: gated by the `auth` + `role:admin,dev` middleware on the route
|
|
27
|
+
* group (boards are a dev-mode surface per #1843). The action body
|
|
28
|
+
* doesn't re-check the role; the middleware did.
|
|
29
|
+
*
|
|
30
|
+
* Phase 1 — read-only. Phase 2 lands store / update / destroy + the
|
|
31
|
+
* reorder endpoint that moves a board's position.
|
|
32
|
+
*/
|
|
33
|
+
export default new Action({
|
|
34
|
+
name: 'Kanban Boards Index',
|
|
35
|
+
description: 'Lists kanban boards with per-board card counts for the dashboard index page.',
|
|
36
|
+
method: 'GET',
|
|
37
|
+
apiResponse: true,
|
|
38
|
+
async handle() {
|
|
39
|
+
try {
|
|
40
|
+
// The card_count is computed via a correlated sub-select rather
|
|
41
|
+
// than a JOIN + GROUP BY so the row shape stays flat. Empty
|
|
42
|
+
// boards return `card_count: 0` instead of being dropped (which
|
|
43
|
+
// is what an inner join + group-by would do).
|
|
44
|
+
const rows = await db.unsafe(`
|
|
45
|
+
SELECT
|
|
46
|
+
b.id, b.uuid, b.name, b.description, b.icon, b.color,
|
|
47
|
+
b.position, b.archived, b.created_at, b.updated_at,
|
|
48
|
+
(SELECT COUNT(*) FROM cards c WHERE c.board_id = b.id AND c.archived = 0) AS card_count
|
|
49
|
+
FROM boards b
|
|
50
|
+
WHERE b.archived = 0
|
|
51
|
+
ORDER BY b.position ASC, b.id ASC
|
|
52
|
+
`).execute() as BoardRow[]
|
|
53
|
+
|
|
54
|
+
const boards = (rows ?? []).map(r => ({
|
|
55
|
+
id: r.id,
|
|
56
|
+
uuid: r.uuid,
|
|
57
|
+
name: r.name,
|
|
58
|
+
description: r.description,
|
|
59
|
+
icon: r.icon,
|
|
60
|
+
color: r.color,
|
|
61
|
+
position: r.position,
|
|
62
|
+
archived: r.archived === 1,
|
|
63
|
+
cardCount: Number(r.card_count ?? 0),
|
|
64
|
+
createdAt: r.created_at,
|
|
65
|
+
updatedAt: r.updated_at,
|
|
66
|
+
}))
|
|
67
|
+
|
|
68
|
+
return { boards }
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
console.error('[dashboard/kanban] BoardsIndexAction failed:', err)
|
|
72
|
+
// Soft-error shape — page renders an empty-state with the
|
|
73
|
+
// message instead of bubbling a 500. Missing `boards` table
|
|
74
|
+
// (migrations not run) ends up here on a fresh project.
|
|
75
|
+
return {
|
|
76
|
+
boards: [],
|
|
77
|
+
error: err instanceof Error ? err.message : 'unknown error',
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
})
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Action } from '@stacksjs/actions'
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
interface ReorderInput {
|
|
5
|
+
/**
|
|
6
|
+
* Ordered list of board ids in their new display order. Array index
|
|
7
|
+
* becomes the row's new `position`. Clients sending a partial list
|
|
8
|
+
* (e.g. only the moved id) will leave other boards' positions
|
|
9
|
+
* untouched — the canonical "after a drag, send the full visible
|
|
10
|
+
* list" semantics avoids drift.
|
|
11
|
+
*/
|
|
12
|
+
order?: unknown
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* `POST /api/dashboard/kanban/boards/reorder` (stacksjs/stacks#1846 Phase 2).
|
|
17
|
+
*
|
|
18
|
+
* Rewrites the `position` column on every board in the submitted list
|
|
19
|
+
* to match its index. Wrapped in a transaction so a partial failure
|
|
20
|
+
* doesn't leave the boards index half-renumbered.
|
|
21
|
+
*
|
|
22
|
+
* Why not PATCH each board's position one-at-a-time? Two reasons:
|
|
23
|
+
* 1. N round-trips become 1 — the page already knows the new order
|
|
24
|
+
* when the drag ends, so we shouldn't pretend it's N independent
|
|
25
|
+
* operations.
|
|
26
|
+
* 2. Atomicity. Mid-flight UI state where some boards have the new
|
|
27
|
+
* position and some don't shows up as out-of-order rendering on
|
|
28
|
+
* the next paint.
|
|
29
|
+
*/
|
|
30
|
+
export default new Action({
|
|
31
|
+
name: 'Kanban Boards Reorder',
|
|
32
|
+
description: 'Bulk-rewrite `position` on a list of boards to match the submitted order.',
|
|
33
|
+
method: 'POST',
|
|
34
|
+
apiResponse: true,
|
|
35
|
+
async handle(request) {
|
|
36
|
+
const body = (request as any).jsonBody as ReorderInput | undefined ?? {}
|
|
37
|
+
if (!Array.isArray(body.order) || body.order.length === 0) {
|
|
38
|
+
return { error: '`order` must be a non-empty array of board ids.', status: 400 }
|
|
39
|
+
}
|
|
40
|
+
const ids: number[] = []
|
|
41
|
+
for (const v of body.order) {
|
|
42
|
+
const n = Number(v)
|
|
43
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
44
|
+
return { error: '`order` contains an invalid id.', status: 400 }
|
|
45
|
+
}
|
|
46
|
+
ids.push(n)
|
|
47
|
+
}
|
|
48
|
+
// Reject duplicates — they'd cause the same row to be written
|
|
49
|
+
// multiple times with the LAST index winning, which silently
|
|
50
|
+
// contradicts the visible order.
|
|
51
|
+
if (new Set(ids).size !== ids.length) {
|
|
52
|
+
return { error: '`order` contains duplicate ids.', status: 400 }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const txOps = async (qb: any) => {
|
|
57
|
+
for (let i = 0; i < ids.length; i++) {
|
|
58
|
+
await qb.updateTable('boards')
|
|
59
|
+
.set({ position: i })
|
|
60
|
+
.where('id', '=', ids[i])
|
|
61
|
+
.execute()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
await (db as any).transaction(txOps)
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// Same fallback rationale as BoardDestroyAction — UPDATE is
|
|
69
|
+
// idempotent for `position` (setting it twice to the same
|
|
70
|
+
// value is a no-op), so a partial run + retry recovers.
|
|
71
|
+
await txOps(db)
|
|
72
|
+
}
|
|
73
|
+
return { reordered: ids.length }
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
console.error('[dashboard/kanban] BoardsReorderAction failed:', err)
|
|
77
|
+
return { error: err instanceof Error ? err.message : 'unknown error', status: 500 }
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
})
|