@stacksjs/defaults 0.70.58 → 0.70.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (575) hide show
  1. package/app/Actions/AI/AskAction.ts +40 -0
  2. package/app/Actions/AI/SummaryAction.ts +40 -0
  3. package/app/Actions/Auth/AuthUserAction.ts +13 -0
  4. package/app/Actions/Auth/CreateTokenAction.ts +64 -0
  5. package/app/Actions/Auth/DisableTwoFactorAction.ts +37 -0
  6. package/app/Actions/Auth/EnableTwoFactorAction.ts +37 -0
  7. package/app/Actions/Auth/GenerateAuthenticationAction.ts +51 -0
  8. package/app/Actions/Auth/GenerateRegistrationAction.ts +53 -0
  9. package/app/Actions/Auth/GenerateTwoFactorSecretAction.ts +26 -0
  10. package/app/Actions/Auth/ListTokensAction.ts +30 -0
  11. package/app/Actions/Auth/LoginAction.ts +73 -0
  12. package/app/Actions/Auth/LogoutAction.ts +16 -0
  13. package/app/Actions/Auth/LogoutAllAction.ts +28 -0
  14. package/app/Actions/Auth/RefreshTokenAction.ts +39 -0
  15. package/app/Actions/Auth/RegisterAction.ts +57 -0
  16. package/app/Actions/Auth/ResendVerificationAction.ts +24 -0
  17. package/app/Actions/Auth/RevokeTokenAction.ts +43 -0
  18. package/app/Actions/Auth/TestAbilitiesAction.ts +61 -0
  19. package/app/Actions/Auth/VerifyAuthenticationAction.ts +94 -0
  20. package/app/Actions/Auth/VerifyEmailAction.ts +25 -0
  21. package/app/Actions/Auth/VerifyRegistrationAction.ts +59 -0
  22. package/app/Actions/Auth/VerifyTwoFactorLoginAction.ts +57 -0
  23. package/app/Actions/Billable/CheckoutAction.ts +25 -0
  24. package/app/Actions/Buddy/BuddyBrowseAction.ts +34 -0
  25. package/app/Actions/Buddy/BuddyCancelAction.ts +32 -0
  26. package/app/Actions/Buddy/BuddyCommitAction.ts +25 -0
  27. package/app/Actions/Buddy/BuddyGitHubConnectAction.ts +40 -0
  28. package/app/Actions/Buddy/BuddyGitHubDisconnectAction.ts +19 -0
  29. package/app/Actions/Buddy/BuddyProcessAction.ts +65 -0
  30. package/app/Actions/Buddy/BuddyProcessStreamAction.ts +128 -0
  31. package/app/Actions/Buddy/BuddyPushAction.ts +21 -0
  32. package/app/Actions/Buddy/BuddyRepoOpenAction.ts +44 -0
  33. package/app/Actions/Buddy/BuddyRepoValidateAction.ts +35 -0
  34. package/app/Actions/Buddy/BuddySettingsAction.ts +21 -0
  35. package/app/Actions/Buddy/BuddySettingsUpdateAction.ts +46 -0
  36. package/app/Actions/Buddy/BuddyStateAction.ts +28 -0
  37. package/app/Actions/Buddy/BuddyTitleAction.ts +49 -0
  38. package/app/Actions/Buddy/CommandsAction.ts +802 -0
  39. package/app/Actions/Buddy/JobCancelAction.ts +32 -0
  40. package/app/Actions/Buddy/JobRetryAction.ts +49 -0
  41. package/app/Actions/Buddy/JobsListAction.ts +141 -0
  42. package/app/Actions/Buddy/ScheduleListAction.ts +52 -0
  43. package/app/Actions/Buddy/VersionsAction.ts +12 -0
  44. package/app/Actions/Cms/AuthorDestroyAction.ts +21 -0
  45. package/app/Actions/Cms/AuthorIndexAction.ts +14 -0
  46. package/app/Actions/Cms/AuthorShowAction.ts +19 -0
  47. package/app/Actions/Cms/AuthorStoreAction.ts +20 -0
  48. package/app/Actions/Cms/AuthorUpdateAction.ts +24 -0
  49. package/app/Actions/Cms/CategorizableDestroyAction.ts +16 -0
  50. package/app/Actions/Cms/CategorizableIndexAction.ts +14 -0
  51. package/app/Actions/Cms/CategorizableShowAction.ts +16 -0
  52. package/app/Actions/Cms/CategorizableStoreAction.ts +42 -0
  53. package/app/Actions/Cms/CategorizableUpdateAction.ts +38 -0
  54. package/app/Actions/Cms/CommentDestroyAction.ts +16 -0
  55. package/app/Actions/Cms/CommentIndexAction.ts +17 -0
  56. package/app/Actions/Cms/CommentShowAction.ts +16 -0
  57. package/app/Actions/Cms/CommentStoreAction.ts +39 -0
  58. package/app/Actions/Cms/CommentUpdateAction.ts +37 -0
  59. package/app/Actions/Cms/PageDestroyAction.ts +16 -0
  60. package/app/Actions/Cms/PageIndexAction.ts +14 -0
  61. package/app/Actions/Cms/PageStoreAction.ts +31 -0
  62. package/app/Actions/Cms/PageUpdateAction.ts +27 -0
  63. package/app/Actions/Cms/PostDestroyAction.ts +17 -0
  64. package/app/Actions/Cms/PostIndexAction.ts +14 -0
  65. package/app/Actions/Cms/PostShowAction.ts +16 -0
  66. package/app/Actions/Cms/PostStoreAction.ts +37 -0
  67. package/app/Actions/Cms/PostUpdateAction.ts +32 -0
  68. package/app/Actions/Cms/PostViewsUpdateAction.ts +34 -0
  69. package/app/Actions/Cms/RssFeedAction.ts +59 -0
  70. package/app/Actions/Cms/SitemapAction.ts +60 -0
  71. package/app/Actions/Cms/TaggableDestroyAction.ts +16 -0
  72. package/app/Actions/Cms/TaggableIndexAction.ts +14 -0
  73. package/app/Actions/Cms/TaggableShowAction.ts +16 -0
  74. package/app/Actions/Cms/TaggableStoreAction.ts +36 -0
  75. package/app/Actions/Cms/TaggableUpdateAction.ts +37 -0
  76. package/app/Actions/Commerce/CouponDestroyAction.ts +18 -0
  77. package/app/Actions/Commerce/CouponIndexAction.ts +16 -0
  78. package/app/Actions/Commerce/CouponShowAction.ts +18 -0
  79. package/app/Actions/Commerce/CouponStoreAction.ts +21 -0
  80. package/app/Actions/Commerce/CouponUpdateAction.ts +31 -0
  81. package/app/Actions/Commerce/CustomerDestroyAction.ts +16 -0
  82. package/app/Actions/Commerce/CustomerIndexAction.ts +15 -0
  83. package/app/Actions/Commerce/CustomerShowAction.ts +18 -0
  84. package/app/Actions/Commerce/CustomerStoreAction.ts +29 -0
  85. package/app/Actions/Commerce/CustomerUpdateAction.ts +27 -0
  86. package/app/Actions/Commerce/DriverDestroyAction.ts +18 -0
  87. package/app/Actions/Commerce/GiftCardDestroyAction.ts +18 -0
  88. package/app/Actions/Commerce/GiftCardIndexAction.ts +16 -0
  89. package/app/Actions/Commerce/GiftCardShowAction.ts +18 -0
  90. package/app/Actions/Commerce/GiftCardStatsAction.ts +30 -0
  91. package/app/Actions/Commerce/GiftCardStoreAction.ts +35 -0
  92. package/app/Actions/Commerce/GiftCardUpdateAction.ts +26 -0
  93. package/app/Actions/Commerce/GiftCardUpdateBalanceAction.ts +36 -0
  94. package/app/Actions/Commerce/OrderDestroyAction.ts +18 -0
  95. package/app/Actions/Commerce/OrderExportAction.ts +15 -0
  96. package/app/Actions/Commerce/OrderIndexAction.ts +15 -0
  97. package/app/Actions/Commerce/OrderShowAction.ts +18 -0
  98. package/app/Actions/Commerce/OrderStoreAction.ts +32 -0
  99. package/app/Actions/Commerce/OrderUpdateAction.ts +34 -0
  100. package/app/Actions/Commerce/PaymentDestroyAction.ts +16 -0
  101. package/app/Actions/Commerce/PaymentFetchStatsAction.ts +31 -0
  102. package/app/Actions/Commerce/PaymentIndexAction.ts +15 -0
  103. package/app/Actions/Commerce/PaymentMonthlyTrendsAction.ts +21 -0
  104. package/app/Actions/Commerce/PaymentShowAction.ts +17 -0
  105. package/app/Actions/Commerce/PaymentStoreAction.ts +24 -0
  106. package/app/Actions/Commerce/PaymentUpdateAction.ts +35 -0
  107. package/app/Actions/Commerce/PrintDeviceDestroyAction.ts +18 -0
  108. package/app/Actions/Commerce/PrintDeviceIndexAction.ts +14 -0
  109. package/app/Actions/Commerce/PrintDeviceShowAction.ts +17 -0
  110. package/app/Actions/Commerce/PrintDeviceStoreAction.ts +27 -0
  111. package/app/Actions/Commerce/PrintDeviceUpdateAction.ts +27 -0
  112. package/app/Actions/Commerce/Product/ManufacturerDestroyAction.ts +20 -0
  113. package/app/Actions/Commerce/Product/ManufacturerIndexAction.ts +16 -0
  114. package/app/Actions/Commerce/Product/ManufacturerShowAction.ts +18 -0
  115. package/app/Actions/Commerce/Product/ManufacturerStoreAction.ts +14 -0
  116. package/app/Actions/Commerce/Product/ProductCategoryIndexAction.ts +16 -0
  117. package/app/Actions/Commerce/Product/ProductCategoryStoreAction.ts +16 -0
  118. package/app/Actions/Commerce/Product/ProductDestroyAction.ts +16 -0
  119. package/app/Actions/Commerce/Product/ProductIndexAction.ts +14 -0
  120. package/app/Actions/Commerce/Product/ProductManufacturerDestroyAction.ts +18 -0
  121. package/app/Actions/Commerce/Product/ProductManufacturerIndexAction.ts +14 -0
  122. package/app/Actions/Commerce/Product/ProductManufacturerShowAction.ts +16 -0
  123. package/app/Actions/Commerce/Product/ProductManufacturerStoreAction.ts +14 -0
  124. package/app/Actions/Commerce/Product/ProductManufacturerUpdateAction.ts +18 -0
  125. package/app/Actions/Commerce/Product/ProductShowAction.ts +18 -0
  126. package/app/Actions/Commerce/Product/ProductStoreAction.ts +17 -0
  127. package/app/Actions/Commerce/Product/ProductUnitDestroyAction.ts +18 -0
  128. package/app/Actions/Commerce/Product/ProductUnitIndexAction.ts +14 -0
  129. package/app/Actions/Commerce/Product/ProductUnitShowAction.ts +18 -0
  130. package/app/Actions/Commerce/Product/ProductUnitStoreAction.ts +15 -0
  131. package/app/Actions/Commerce/Product/ProductUpdateAction.ts +17 -0
  132. package/app/Actions/Commerce/Product/ProductVariantDestroyAction.ts +18 -0
  133. package/app/Actions/Commerce/Product/ProductVariantIndexAction.ts +14 -0
  134. package/app/Actions/Commerce/Product/ProductVariantShowAction.ts +17 -0
  135. package/app/Actions/Commerce/Product/ProductVariantStoreAction.ts +14 -0
  136. package/app/Actions/Commerce/Product/ProductVariantUpdateAction.ts +16 -0
  137. package/app/Actions/Commerce/ReceiptDestroyAction.ts +18 -0
  138. package/app/Actions/Commerce/ReceiptIndexAction.ts +14 -0
  139. package/app/Actions/Commerce/ReceiptShowAction.ts +18 -0
  140. package/app/Actions/Commerce/ReceiptStoreAction.ts +28 -0
  141. package/app/Actions/Commerce/ReceiptUpdateAction.ts +30 -0
  142. package/app/Actions/Commerce/ReviewIndexAction.ts +14 -0
  143. package/app/Actions/Commerce/ReviewShowAction.ts +16 -0
  144. package/app/Actions/Commerce/ReviewStoreAction.ts +26 -0
  145. package/app/Actions/Commerce/ReviewUpdateAction.ts +28 -0
  146. package/app/Actions/Commerce/Shipping/DeliveryRouteDestroyAction.ts +18 -0
  147. package/app/Actions/Commerce/Shipping/DeliveryRouteIndexAction.ts +16 -0
  148. package/app/Actions/Commerce/Shipping/DeliveryRouteShowAction.ts +18 -0
  149. package/app/Actions/Commerce/Shipping/DeliveryRouteStoreAction.ts +16 -0
  150. package/app/Actions/Commerce/Shipping/DeliveryRouteUpdateAction.ts +18 -0
  151. package/app/Actions/Commerce/Shipping/DigitalDeliveryDestroyAction.ts +18 -0
  152. package/app/Actions/Commerce/Shipping/DigitalDeliveryIndexAction.ts +16 -0
  153. package/app/Actions/Commerce/Shipping/DigitalDeliveryShowAction.ts +18 -0
  154. package/app/Actions/Commerce/Shipping/DigitalDeliveryStoreAction.ts +18 -0
  155. package/app/Actions/Commerce/Shipping/DigitalDeliveryUpdateAction.ts +18 -0
  156. package/app/Actions/Commerce/Shipping/DriverIndexAction.ts +16 -0
  157. package/app/Actions/Commerce/Shipping/DriverShowAction.ts +18 -0
  158. package/app/Actions/Commerce/Shipping/DriverStoreAction.ts +16 -0
  159. package/app/Actions/Commerce/Shipping/DriverUpdateAction.ts +18 -0
  160. package/app/Actions/Commerce/Shipping/LicenseKeyDestroyAction.ts +20 -0
  161. package/app/Actions/Commerce/Shipping/LicenseKeyIndexAction.ts +16 -0
  162. package/app/Actions/Commerce/Shipping/LicenseKeyShowAction.ts +18 -0
  163. package/app/Actions/Commerce/Shipping/LicenseKeyStoreAction.ts +18 -0
  164. package/app/Actions/Commerce/Shipping/LicenseKeyUpdateAction.ts +18 -0
  165. package/app/Actions/Commerce/Shipping/ShippingMethodDestroyAction.ts +16 -0
  166. package/app/Actions/Commerce/Shipping/ShippingMethodIndexAction.ts +14 -0
  167. package/app/Actions/Commerce/Shipping/ShippingMethodShowAction.ts +16 -0
  168. package/app/Actions/Commerce/Shipping/ShippingMethodStoreAction.ts +16 -0
  169. package/app/Actions/Commerce/Shipping/ShippingMethodUpdateAction.ts +15 -0
  170. package/app/Actions/Commerce/Shipping/ShippingRateDestroyAction.ts +16 -0
  171. package/app/Actions/Commerce/Shipping/ShippingRateIndexAction.ts +14 -0
  172. package/app/Actions/Commerce/Shipping/ShippingRateShowAction.ts +16 -0
  173. package/app/Actions/Commerce/Shipping/ShippingRateStoreAction.ts +16 -0
  174. package/app/Actions/Commerce/Shipping/ShippingRateUpdateAction.ts +17 -0
  175. package/app/Actions/Commerce/Shipping/ShippingZoneDestroyAction.ts +16 -0
  176. package/app/Actions/Commerce/Shipping/ShippingZoneIndexAction.ts +14 -0
  177. package/app/Actions/Commerce/Shipping/ShippingZoneShowAction.ts +16 -0
  178. package/app/Actions/Commerce/Shipping/ShippingZoneStoreAction.ts +16 -0
  179. package/app/Actions/Commerce/Shipping/ShippingZoneUpdateAction.ts +15 -0
  180. package/app/Actions/Commerce/TaxRateDestroyAction.ts +16 -0
  181. package/app/Actions/Commerce/TaxRateIndexAction.ts +14 -0
  182. package/app/Actions/Commerce/TaxRateShowAction.ts +17 -0
  183. package/app/Actions/Commerce/TaxRateStoreAction.ts +24 -0
  184. package/app/Actions/Commerce/TaxRateUpdateAction.ts +24 -0
  185. package/app/Actions/Commerce/WaitlistProductAnalyticsAction.ts +29 -0
  186. package/app/Actions/Commerce/WaitlistProductDestroyAction.ts +16 -0
  187. package/app/Actions/Commerce/WaitlistProductIndexAction.ts +14 -0
  188. package/app/Actions/Commerce/WaitlistProductQuantityDistributionAction.ts +32 -0
  189. package/app/Actions/Commerce/WaitlistProductShowAction.ts +16 -0
  190. package/app/Actions/Commerce/WaitlistProductStatusAction.ts +37 -0
  191. package/app/Actions/Commerce/WaitlistProductStoreAction.ts +27 -0
  192. package/app/Actions/Commerce/WaitlistProductTimeSeriesAction.ts +25 -0
  193. package/app/Actions/Commerce/WaitlistProductUpdateAction.ts +29 -0
  194. package/app/Actions/Commerce/WaitlistRestaurantDashboardAction.ts +29 -0
  195. package/app/Actions/Commerce/WaitlistRestaurantDestroyAction.ts +16 -0
  196. package/app/Actions/Commerce/WaitlistRestaurantIndexAction.ts +14 -0
  197. package/app/Actions/Commerce/WaitlistRestaurantShowAction.ts +16 -0
  198. package/app/Actions/Commerce/WaitlistRestaurantStoreAction.ts +31 -0
  199. package/app/Actions/Commerce/WaitlistRestaurantUpdateAction.ts +33 -0
  200. package/app/Actions/ContactAction.ts +72 -0
  201. package/app/Actions/Dashboard/Actions/CreateAction.ts +11 -0
  202. package/app/Actions/Dashboard/Actions/GetActionCount.ts +12 -0
  203. package/app/Actions/Dashboard/Actions/GetActions.ts +19 -0
  204. package/app/Actions/Dashboard/Analytics/BlogAnalyticsAction.ts +58 -0
  205. package/app/Actions/Dashboard/Analytics/BrowserAnalyticsAction.ts +42 -0
  206. package/app/Actions/Dashboard/Analytics/CommerceAnalyticsAction.ts +64 -0
  207. package/app/Actions/Dashboard/Analytics/CountryAnalyticsAction.ts +41 -0
  208. package/app/Actions/Dashboard/Analytics/DeviceAnalyticsAction.ts +58 -0
  209. package/app/Actions/Dashboard/Analytics/EventAnalyticsAction.ts +90 -0
  210. package/app/Actions/Dashboard/Analytics/MarketingAnalyticsAction.ts +76 -0
  211. package/app/Actions/Dashboard/Analytics/PageAnalyticsAction.ts +45 -0
  212. package/app/Actions/Dashboard/Analytics/ReferrerAnalyticsAction.ts +72 -0
  213. package/app/Actions/Dashboard/Analytics/SalesAnalyticsAction.ts +73 -0
  214. package/app/Actions/Dashboard/Analytics/WebAnalyticsAction.ts +114 -0
  215. package/app/Actions/Dashboard/Auth/MeAction.ts +84 -0
  216. package/app/Actions/Dashboard/BuddyDashboardAction.ts +34 -0
  217. package/app/Actions/Dashboard/Ci/RepoRunJobsAction.ts +60 -0
  218. package/app/Actions/Dashboard/Ci/RepoRunsAction.ts +67 -0
  219. package/app/Actions/Dashboard/Ci/RunnerHistoryAction.ts +58 -0
  220. package/app/Actions/Dashboard/Ci/StatusAction.ts +73 -0
  221. package/app/Actions/Dashboard/Ci/failure-notifier.ts +214 -0
  222. package/app/Actions/Dashboard/Ci/runner-pressure-monitor.ts +259 -0
  223. package/app/Actions/Dashboard/Cloud/CloudIndexAction.ts +61 -0
  224. package/app/Actions/Dashboard/Commands/CreateCommand.ts +11 -0
  225. package/app/Actions/Dashboard/Commands/GetAverageCommandTime.ts +12 -0
  226. package/app/Actions/Dashboard/Commands/GetCommandCount.ts +12 -0
  227. package/app/Actions/Dashboard/Commands/GetCommandSuccessRate.ts +12 -0
  228. package/app/Actions/Dashboard/Commands/GetCommands.ts +12 -0
  229. package/app/Actions/Dashboard/Commerce/CommerceCouponsAction.ts +48 -0
  230. package/app/Actions/Dashboard/Commerce/CommerceCustomersAction.ts +48 -0
  231. package/app/Actions/Dashboard/Commerce/CommerceDashboardAction.ts +98 -0
  232. package/app/Actions/Dashboard/Commerce/CommerceDeliveryAction.ts +65 -0
  233. package/app/Actions/Dashboard/Commerce/CommerceGiftCardsAction.ts +48 -0
  234. package/app/Actions/Dashboard/Commerce/CommerceOrdersAction.ts +51 -0
  235. package/app/Actions/Dashboard/Commerce/CommercePaymentsAction.ts +59 -0
  236. package/app/Actions/Dashboard/Commerce/CommerceProductsAction.ts +50 -0
  237. package/app/Actions/Dashboard/Commerce/CommerceTaxesAction.ts +46 -0
  238. package/app/Actions/Dashboard/Commerce/PosIndexAction.ts +57 -0
  239. package/app/Actions/Dashboard/Commerce/ReviewIndexAction.ts +51 -0
  240. package/app/Actions/Dashboard/Content/AuthorIndexAction.ts +51 -0
  241. package/app/Actions/Dashboard/Content/CategoryIndexAction.ts +27 -0
  242. package/app/Actions/Dashboard/Content/CommentIndexAction.ts +41 -0
  243. package/app/Actions/Dashboard/Content/ContentDashboardAction.ts +54 -0
  244. package/app/Actions/Dashboard/Content/FileIndexAction.ts +24 -0
  245. package/app/Actions/Dashboard/Content/PageIndexAction.ts +25 -0
  246. package/app/Actions/Dashboard/Content/PostIndexAction.ts +102 -0
  247. package/app/Actions/Dashboard/Content/SeoIndexAction.ts +17 -0
  248. package/app/Actions/Dashboard/Content/TagIndexAction.ts +23 -0
  249. package/app/Actions/Dashboard/CreateDnsRecords.ts +11 -0
  250. package/app/Actions/Dashboard/CreateMailbox.ts +11 -0
  251. package/app/Actions/Dashboard/DashboardActivityAction.ts +58 -0
  252. package/app/Actions/Dashboard/DashboardHealthAction.ts +52 -0
  253. package/app/Actions/Dashboard/DashboardHomeAction.ts +83 -0
  254. package/app/Actions/Dashboard/DashboardStatsAction.ts +48 -0
  255. package/app/Actions/Dashboard/Data/AccessTokenIndexAction.ts +65 -0
  256. package/app/Actions/Dashboard/Data/ActivityIndexAction.ts +28 -0
  257. package/app/Actions/Dashboard/Data/DataDashboardAction.ts +67 -0
  258. package/app/Actions/Dashboard/Data/SubscriberIndexAction.ts +48 -0
  259. package/app/Actions/Dashboard/Data/TeamIndexAction.ts +43 -0
  260. package/app/Actions/Dashboard/Data/UserIndexAction.ts +48 -0
  261. package/app/Actions/Dashboard/Deployments/CreateDeployment.ts +11 -0
  262. package/app/Actions/Dashboard/Deployments/GetAverageDeploymentTime.ts +15 -0
  263. package/app/Actions/Dashboard/Deployments/GetDeployScript.ts +12 -0
  264. package/app/Actions/Dashboard/Deployments/GetDeploymentCount.ts +12 -0
  265. package/app/Actions/Dashboard/Deployments/GetDeploymentLiveTerminalOutput.ts +12 -0
  266. package/app/Actions/Dashboard/Deployments/GetDeployments.ts +20 -0
  267. package/app/Actions/Dashboard/Deployments/GetRecentDeployments.ts +12 -0
  268. package/app/Actions/Dashboard/Deployments/UpdateDeployScript.ts +11 -0
  269. package/app/Actions/Dashboard/GetDnsRecords.ts +12 -0
  270. package/app/Actions/Dashboard/GetEmailInboxes.ts +12 -0
  271. package/app/Actions/Dashboard/GetProjects.ts +13 -0
  272. package/app/Actions/Dashboard/GetRecentCommits.ts +13 -0
  273. package/app/Actions/Dashboard/Inbox/InboxIndexAction.ts +144 -0
  274. package/app/Actions/Dashboard/Inbox/InboxShowAction.ts +89 -0
  275. package/app/Actions/Dashboard/Infrastructure/CommandIndexAction.ts +18 -0
  276. package/app/Actions/Dashboard/Infrastructure/DnsIndexAction.ts +101 -0
  277. package/app/Actions/Dashboard/Infrastructure/EnvironmentIndexAction.ts +67 -0
  278. package/app/Actions/Dashboard/Infrastructure/InsightsAction.ts +29 -0
  279. package/app/Actions/Dashboard/Infrastructure/LogIndexAction.ts +50 -0
  280. package/app/Actions/Dashboard/Infrastructure/MailboxIndexAction.ts +85 -0
  281. package/app/Actions/Dashboard/Infrastructure/PermissionIndexAction.ts +54 -0
  282. package/app/Actions/Dashboard/Infrastructure/RequestIndexAction.ts +44 -0
  283. package/app/Actions/Dashboard/Infrastructure/ServerIndexAction.ts +101 -0
  284. package/app/Actions/Dashboard/Jobs/CreateJob.ts +11 -0
  285. package/app/Actions/Dashboard/Jobs/GetAverageJobTime.ts +12 -0
  286. package/app/Actions/Dashboard/Jobs/GetJobHistory.ts +12 -0
  287. package/app/Actions/Dashboard/Jobs/GetJobs.ts +11 -0
  288. package/app/Actions/Dashboard/Jobs/GetJobsPerMinute.ts +12 -0
  289. package/app/Actions/Dashboard/Jobs/JobIndexAction.ts +136 -0
  290. package/app/Actions/Dashboard/Jobs/JobRetryAction.ts +23 -0
  291. package/app/Actions/Dashboard/Jobs/JobStatsAction.ts +49 -0
  292. package/app/Actions/Dashboard/Kanban/BoardDestroyAction.ts +84 -0
  293. package/app/Actions/Dashboard/Kanban/BoardShowAction.ts +215 -0
  294. package/app/Actions/Dashboard/Kanban/BoardStoreAction.ts +98 -0
  295. package/app/Actions/Dashboard/Kanban/BoardUpdateAction.ts +96 -0
  296. package/app/Actions/Dashboard/Kanban/BoardsIndexAction.ts +81 -0
  297. package/app/Actions/Dashboard/Kanban/BoardsReorderAction.ts +80 -0
  298. package/app/Actions/Dashboard/Kanban/CardAssigneesSyncAction.ts +103 -0
  299. package/app/Actions/Dashboard/Kanban/CardCommentDestroyAction.ts +33 -0
  300. package/app/Actions/Dashboard/Kanban/CardCommentStoreAction.ts +82 -0
  301. package/app/Actions/Dashboard/Kanban/CardDestroyAction.ts +48 -0
  302. package/app/Actions/Dashboard/Kanban/CardLabelsSyncAction.ts +103 -0
  303. package/app/Actions/Dashboard/Kanban/CardShowAction.ts +122 -0
  304. package/app/Actions/Dashboard/Kanban/CardStoreAction.ts +112 -0
  305. package/app/Actions/Dashboard/Kanban/CardUpdateAction.ts +91 -0
  306. package/app/Actions/Dashboard/Kanban/CardsReorderAction.ts +148 -0
  307. package/app/Actions/Dashboard/Kanban/ColumnDestroyAction.ts +59 -0
  308. package/app/Actions/Dashboard/Kanban/ColumnStoreAction.ts +94 -0
  309. package/app/Actions/Dashboard/Kanban/ColumnUpdateAction.ts +89 -0
  310. package/app/Actions/Dashboard/Kanban/ColumnsReorderAction.ts +85 -0
  311. package/app/Actions/Dashboard/Kanban/LabelDestroyAction.ts +41 -0
  312. package/app/Actions/Dashboard/Kanban/LabelStoreAction.ts +70 -0
  313. package/app/Actions/Dashboard/Kanban/LabelUpdateAction.ts +83 -0
  314. package/app/Actions/Dashboard/Kanban/UsersListAction.ts +36 -0
  315. package/app/Actions/Dashboard/Library/CreateComponent.ts +11 -0
  316. package/app/Actions/Dashboard/Library/CreateFunction.ts +11 -0
  317. package/app/Actions/Dashboard/Library/DependencyIndexAction.ts +92 -0
  318. package/app/Actions/Dashboard/Library/GetAverageReleaseTime.ts +12 -0
  319. package/app/Actions/Dashboard/Library/GetComponents.ts +24 -0
  320. package/app/Actions/Dashboard/Library/GetComponentsDownloadCount.ts +12 -0
  321. package/app/Actions/Dashboard/Library/GetDownloadCount.ts +12 -0
  322. package/app/Actions/Dashboard/Library/GetFunctions.ts +22 -0
  323. package/app/Actions/Dashboard/Library/GetFunctionsDownloadCount.ts +12 -0
  324. package/app/Actions/Dashboard/Library/GetReleaseCount.ts +12 -0
  325. package/app/Actions/Dashboard/Library/GetReleases.ts +28 -0
  326. package/app/Actions/Dashboard/Library/PackageIndexAction.ts +26 -0
  327. package/app/Actions/Dashboard/Marketing/CampaignIndexAction.ts +45 -0
  328. package/app/Actions/Dashboard/Marketing/ListIndexAction.ts +43 -0
  329. package/app/Actions/Dashboard/Marketing/SocialPostIndexAction.ts +47 -0
  330. package/app/Actions/Dashboard/Models/GetModels.ts +39 -0
  331. package/app/Actions/Dashboard/Models/GetSubscriberCount.ts +12 -0
  332. package/app/Actions/Dashboard/Models/GetUserCount.ts +12 -0
  333. package/app/Actions/Dashboard/Models/ModelShowAction.ts +131 -0
  334. package/app/Actions/Dashboard/Models/ModelsIndexAction.ts +169 -0
  335. package/app/Actions/Dashboard/Notifications/CreateNotification.ts +11 -0
  336. package/app/Actions/Dashboard/Notifications/GetAverageNotificationTime.ts +12 -0
  337. package/app/Actions/Dashboard/Notifications/GetNotificationCount.ts +12 -0
  338. package/app/Actions/Dashboard/Notifications/GetNotificationDeliveryRate.ts +12 -0
  339. package/app/Actions/Dashboard/Notifications/GetNotificationHistory.ts +12 -0
  340. package/app/Actions/Dashboard/Notifications/GetNotifications.ts +12 -0
  341. package/app/Actions/Dashboard/Notifications/NotificationDashboardAction.ts +43 -0
  342. package/app/Actions/Dashboard/Queries/QueryIndexAction.ts +22 -0
  343. package/app/Actions/Dashboard/Queue/QueueRetryFailedAction.ts +22 -0
  344. package/app/Actions/Dashboard/Queue/QueueStatsAction.ts +98 -0
  345. package/app/Actions/Dashboard/Queue/QueueWorkersAction.ts +46 -0
  346. package/app/Actions/Dashboard/Rbac/PermissionDestroyAction.ts +33 -0
  347. package/app/Actions/Dashboard/Rbac/PermissionStoreAction.ts +53 -0
  348. package/app/Actions/Dashboard/Rbac/PermissionsIndexAction.ts +34 -0
  349. package/app/Actions/Dashboard/Rbac/RoleDestroyAction.ts +35 -0
  350. package/app/Actions/Dashboard/Rbac/RolePermissionsShowAction.ts +45 -0
  351. package/app/Actions/Dashboard/Rbac/RolePermissionsSyncAction.ts +63 -0
  352. package/app/Actions/Dashboard/Rbac/RoleStoreAction.ts +58 -0
  353. package/app/Actions/Dashboard/Rbac/RolesIndexAction.ts +36 -0
  354. package/app/Actions/Dashboard/Rbac/UserRolesShowAction.ts +40 -0
  355. package/app/Actions/Dashboard/Rbac/UserRolesSyncAction.ts +65 -0
  356. package/app/Actions/Dashboard/Rbac/UsersListAction.ts +39 -0
  357. package/app/Actions/Dashboard/Realtime/RealtimeStatsAction.ts +50 -0
  358. package/app/Actions/Dashboard/Releases/ReleaseIndexAction.ts +21 -0
  359. package/app/Actions/Dashboard/Requests/GetAverageRequestTime.ts +12 -0
  360. package/app/Actions/Dashboard/Requests/GetRequestCount.ts +12 -0
  361. package/app/Actions/Dashboard/Requests/GetRequestSuccessRate.ts +12 -0
  362. package/app/Actions/Dashboard/Requests/GetRequests.ts +12 -0
  363. package/app/Actions/Dashboard/Search/GlobalSearchAction.ts +26 -0
  364. package/app/Actions/Dashboard/ServiceHealthAction.ts +243 -0
  365. package/app/Actions/Dashboard/Settings/MailSettingsGetAction.ts +20 -0
  366. package/app/Actions/Dashboard/Settings/MailSettingsUpdateAction.ts +10 -0
  367. package/app/Actions/Dashboard/Settings/SettingsIndexAction.ts +40 -0
  368. package/app/Actions/Dashboard/Settings/UpdateAiConfig.ts +27 -0
  369. package/app/Actions/Dashboard/Settings/UpdateAnalyticsConfig.ts +38 -0
  370. package/app/Actions/Dashboard/Settings/UpdateAppConfig.ts +38 -0
  371. package/app/Actions/Dashboard/Settings/UpdateCacheConfig.ts +11 -0
  372. package/app/Actions/Dashboard/Settings/UpdateCliConfig.ts +11 -0
  373. package/app/Actions/Dashboard/Settings/UpdateCloudConfig.ts +38 -0
  374. package/app/Actions/Dashboard/Settings/UpdateDatabaseConfig.ts +38 -0
  375. package/app/Actions/Dashboard/Settings/UpdateDnsConfig.ts +38 -0
  376. package/app/Actions/Dashboard/Settings/UpdateDocsConfig.ts +11 -0
  377. package/app/Actions/Dashboard/Settings/UpdateEmailConfig.ts +38 -0
  378. package/app/Actions/Dashboard/Settings/UpdateEnvConfig.ts +11 -0
  379. package/app/Actions/Dashboard/Settings/UpdateErrorsConfig.ts +11 -0
  380. package/app/Actions/Dashboard/Settings/UpdateFileSystemsConfig.ts +11 -0
  381. package/app/Actions/Dashboard/Settings/UpdateGitConfig.ts +11 -0
  382. package/app/Actions/Dashboard/Settings/UpdateHashingConfig.ts +11 -0
  383. package/app/Actions/Dashboard/Settings/UpdateLibraryConfig.ts +11 -0
  384. package/app/Actions/Dashboard/Settings/UpdateLoggerConfig.ts +11 -0
  385. package/app/Actions/Dashboard/Settings/UpdateNotificationConfig.ts +11 -0
  386. package/app/Actions/Dashboard/Settings/UpdatePaymentConfig.ts +11 -0
  387. package/app/Actions/Dashboard/Settings/UpdatePortsConfig.ts +38 -0
  388. package/app/Actions/Dashboard/Settings/UpdateQueueConfig.ts +11 -0
  389. package/app/Actions/Dashboard/Settings/UpdateSearchEngineConfig.ts +11 -0
  390. package/app/Actions/Dashboard/Settings/UpdateSecurityConfig.ts +38 -0
  391. package/app/Actions/Dashboard/Settings/UpdateServicesConfig.ts +38 -0
  392. package/app/Actions/Dashboard/Settings/UpdateStorageConfig.ts +11 -0
  393. package/app/Actions/Dashboard/Settings/UpdateTeamConfig.ts +11 -0
  394. package/app/Actions/Dashboard/Settings/UpdateUiConfig.ts +11 -0
  395. package/app/Actions/HealthAction.ts +112 -0
  396. package/app/Actions/InstallAction.ts +83 -0
  397. package/app/Actions/Locale/SetLocaleAction.ts +51 -0
  398. package/app/Actions/LogAction.ts +42 -0
  399. package/app/Actions/Logs/LogFetchStatsAction.ts +50 -0
  400. package/app/Actions/Logs/LogIndexOrmAction.ts +13 -0
  401. package/app/Actions/Logs/LogShowOrmAction.ts +17 -0
  402. package/app/Actions/Logs/LogStoreOrmAction.ts +16 -0
  403. package/app/Actions/Logs/LogUpdateOrmAction.ts +20 -0
  404. package/app/Actions/Monitoring/ErrorDestroyAction.ts +25 -0
  405. package/app/Actions/Monitoring/ErrorGroupAction.ts +21 -0
  406. package/app/Actions/Monitoring/ErrorIgnoreAction.ts +25 -0
  407. package/app/Actions/Monitoring/ErrorIndexAction.ts +14 -0
  408. package/app/Actions/Monitoring/ErrorResolveAction.ts +25 -0
  409. package/app/Actions/Monitoring/ErrorShowAction.ts +19 -0
  410. package/app/Actions/Monitoring/ErrorStatsAction.ts +14 -0
  411. package/app/Actions/Monitoring/ErrorTimelineAction.ts +14 -0
  412. package/app/Actions/Monitoring/ErrorUnresolveAction.ts +25 -0
  413. package/app/Actions/NotifyUser.ts +10 -0
  414. package/app/Actions/Password/PasswordResetAction.ts +54 -0
  415. package/app/Actions/Password/SendPasswordResetEmailAction.ts +66 -0
  416. package/app/Actions/Password/VerifyResetTokenAction.ts +27 -0
  417. package/app/Actions/Payment/CancelSubscriptionAction.ts +20 -0
  418. package/app/Actions/Payment/CreateCheckoutAction.ts +28 -0
  419. package/app/Actions/Payment/CreateInvoiceSubscription.ts +18 -0
  420. package/app/Actions/Payment/CreatePaymentIntentAction.ts +31 -0
  421. package/app/Actions/Payment/CreateSetupIntentAction.ts +20 -0
  422. package/app/Actions/Payment/CreateSubscriptionAction.ts +23 -0
  423. package/app/Actions/Payment/DeleteDefaultPaymentAction.ts +18 -0
  424. package/app/Actions/Payment/FetchActiveSubscriptionAction.ts +18 -0
  425. package/app/Actions/Payment/FetchDefaultPaymentMethodAction.ts +18 -0
  426. package/app/Actions/Payment/FetchPaymentCustomerAction.ts +18 -0
  427. package/app/Actions/Payment/FetchPaymentMethodsAction.ts +18 -0
  428. package/app/Actions/Payment/FetchProductAction.ts +15 -0
  429. package/app/Actions/Payment/FetchTransactionHistoryAction.ts +18 -0
  430. package/app/Actions/Payment/FetchUserSubscriptionsAction.ts +18 -0
  431. package/app/Actions/Payment/SetDefaultPaymentAction.ts +20 -0
  432. package/app/Actions/Payment/SetUserDefaultPaymentAction.ts +20 -0
  433. package/app/Actions/Payment/StorePaymentMethodAction.ts +20 -0
  434. package/app/Actions/Payment/StoreTransactionAction.ts +20 -0
  435. package/app/Actions/Payment/UpdateCustomerAction.ts +24 -0
  436. package/app/Actions/Payment/UpdateDefaultPaymentMethodAction.ts +18 -0
  437. package/app/Actions/Payment/UpdateSubscriptionAction.ts +22 -0
  438. package/app/Actions/Queue/FetchQueuesAction.ts +14 -0
  439. package/app/Actions/README.md +61 -0
  440. package/app/Actions/Realtime/FetchWebsocketsAction.ts +14 -0
  441. package/app/Actions/RobotsAction.ts +61 -0
  442. package/app/Actions/SendWelcomeEmail.ts +40 -0
  443. package/app/Actions/SitemapAction.ts +234 -0
  444. package/app/Actions/Storefront/AddToCartAction.ts +153 -0
  445. package/app/Actions/Storefront/CheckoutContactAction.ts +50 -0
  446. package/app/Actions/Storefront/CheckoutShippingAction.ts +61 -0
  447. package/app/Actions/Storefront/GetCartAction.ts +58 -0
  448. package/app/Actions/Storefront/PlaceOrderAction.ts +195 -0
  449. package/app/Actions/Storefront/SubmitReviewAction.ts +140 -0
  450. package/app/Actions/Storefront/UpdateCartItemAction.ts +83 -0
  451. package/app/Actions/Storefront/_shipping.ts +64 -0
  452. package/app/Actions/SubscriberEmailAction.ts +60 -0
  453. package/app/Actions/TestErrorAction.ts +163 -0
  454. package/app/Actions/UnsubscribeAction.ts +107 -0
  455. package/app/Actions/UploadTestAction.ts +57 -0
  456. package/app/Broadcasts/OrderShipped.ts +57 -0
  457. package/app/Commands/Inspire.ts +57 -0
  458. package/app/Commands/README.md +84 -0
  459. package/app/Commands.ts +38 -0
  460. package/app/Controllers/ComingSoonController.ts +9 -0
  461. package/app/Controllers/QueryController.ts +373 -0
  462. package/app/Events.ts +14 -0
  463. package/app/Gates.ts +107 -0
  464. package/app/Jobs/ExampleJob.ts +20 -0
  465. package/app/Jobs/ExampleTwoJob.ts +12 -0
  466. package/app/Jobs/PruneModelsJob.ts +61 -0
  467. package/app/Jobs/PruneQueryLogsJob.ts +51 -0
  468. package/app/Jobs/README.md +79 -0
  469. package/app/Jobs/SendCampaignJob.ts +201 -0
  470. package/app/Jobs/SendEmailJob.ts +52 -0
  471. package/app/Jobs/SendPasswordResetEmailJob.ts +44 -0
  472. package/app/Jobs/SyncSearchIndexJob.ts +64 -0
  473. package/app/Listener.ts +84 -0
  474. package/app/Listeners/Console.ts +22 -0
  475. package/app/Listeners/README.md +47 -0
  476. package/app/Mail/OrderConfirmation.ts +60 -0
  477. package/app/Mail/SubscriptionConfirmation.ts +41 -0
  478. package/app/Middleware/Abilities.ts +53 -0
  479. package/app/Middleware/Api.ts +26 -0
  480. package/app/Middleware/Auth.ts +59 -0
  481. package/app/Middleware/Can.ts +68 -0
  482. package/app/Middleware/Compress.ts +213 -0
  483. package/app/Middleware/Cors.ts +320 -0
  484. package/app/Middleware/Csrf.ts +224 -0
  485. package/app/Middleware/EnsureEmailIsVerified.ts +28 -0
  486. package/app/Middleware/Env.ts +24 -0
  487. package/app/Middleware/EnvDevelopment.ts +19 -0
  488. package/app/Middleware/EnvLocal.ts +19 -0
  489. package/app/Middleware/EnvNotDevelopment.ts +19 -0
  490. package/app/Middleware/EnvNotLocal.ts +19 -0
  491. package/app/Middleware/EnvNotProduction.ts +19 -0
  492. package/app/Middleware/EnvNotStaging.ts +19 -0
  493. package/app/Middleware/EnvProduction.ts +19 -0
  494. package/app/Middleware/EnvStaging.ts +19 -0
  495. package/app/Middleware/Guest.ts +25 -0
  496. package/app/Middleware/Logger.ts +20 -0
  497. package/app/Middleware/Maintenance.ts +36 -0
  498. package/app/Middleware/Permission.ts +42 -0
  499. package/app/Middleware/README.md +48 -0
  500. package/app/Middleware/Role.ts +42 -0
  501. package/app/Middleware/Signed.ts +31 -0
  502. package/app/Middleware/Team.ts +36 -0
  503. package/app/Middleware/Throttle.ts +96 -0
  504. package/app/Middleware.ts +35 -0
  505. package/app/Models/Activity.ts +94 -0
  506. package/app/Models/Board.ts +103 -0
  507. package/app/Models/BoardColumn.ts +87 -0
  508. package/app/Models/Campaign.ts +239 -0
  509. package/app/Models/CampaignSend.ts +107 -0
  510. package/app/Models/Card.ts +117 -0
  511. package/app/Models/CardComment.ts +68 -0
  512. package/app/Models/Comment.ts +108 -0
  513. package/app/Models/Content/Author.ts +104 -0
  514. package/app/Models/Content/Page.ts +99 -0
  515. package/app/Models/Content/Post.ts +144 -0
  516. package/app/Models/Deployment.ts +116 -0
  517. package/app/Models/EmailList.ts +126 -0
  518. package/app/Models/EmailListSubscriber.ts +91 -0
  519. package/app/Models/Error.ts +70 -0
  520. package/app/Models/FailedJob.ts +62 -0
  521. package/app/Models/Job.ts +63 -0
  522. package/app/Models/Label.ts +66 -0
  523. package/app/Models/Log.ts +110 -0
  524. package/app/Models/Notification.ts +118 -0
  525. package/app/Models/PaymentMethod.ts +98 -0
  526. package/app/Models/PaymentProduct.ts +91 -0
  527. package/app/Models/PaymentTransaction.ts +78 -0
  528. package/app/Models/README.md +31 -0
  529. package/app/Models/Release.ts +89 -0
  530. package/app/Models/Request.ts +114 -0
  531. package/app/Models/SocialPost.ts +136 -0
  532. package/app/Models/Subscriber.ts +89 -0
  533. package/app/Models/SubscriberEmail.ts +55 -0
  534. package/app/Models/Subscription.ts +153 -0
  535. package/app/Models/Tag.ts +82 -0
  536. package/app/Models/Team.ts +72 -0
  537. package/app/Models/User.ts +134 -0
  538. package/app/Models/commerce/Cart.ts +139 -0
  539. package/app/Models/commerce/CartItem.ts +137 -0
  540. package/app/Models/commerce/Category.ts +105 -0
  541. package/app/Models/commerce/Coupon.ts +181 -0
  542. package/app/Models/commerce/Customer.ts +132 -0
  543. package/app/Models/commerce/DeliveryRoute.ts +93 -0
  544. package/app/Models/commerce/DigitalDelivery.ts +105 -0
  545. package/app/Models/commerce/Driver.ts +97 -0
  546. package/app/Models/commerce/GiftCard.ts +191 -0
  547. package/app/Models/commerce/LicenseKey.ts +87 -0
  548. package/app/Models/commerce/LoyaltyPoint.ts +107 -0
  549. package/app/Models/commerce/LoyaltyReward.ts +124 -0
  550. package/app/Models/commerce/Manufacturer.ts +84 -0
  551. package/app/Models/commerce/Order.ts +142 -0
  552. package/app/Models/commerce/OrderItem.ts +51 -0
  553. package/app/Models/commerce/Payment.ts +163 -0
  554. package/app/Models/commerce/PrintDevice.ts +117 -0
  555. package/app/Models/commerce/Product.ts +148 -0
  556. package/app/Models/commerce/ProductUnit.ts +107 -0
  557. package/app/Models/commerce/ProductVariant.ts +106 -0
  558. package/app/Models/commerce/Receipt.ts +128 -0
  559. package/app/Models/commerce/Review.ts +140 -0
  560. package/app/Models/commerce/ShippingMethod.ts +97 -0
  561. package/app/Models/commerce/ShippingRate.ts +74 -0
  562. package/app/Models/commerce/ShippingZone.ts +111 -0
  563. package/app/Models/commerce/TaxRate.ts +114 -0
  564. package/app/Models/commerce/Transaction.ts +126 -0
  565. package/app/Models/commerce/WaitlistProduct.ts +149 -0
  566. package/app/Models/commerce/WaitlistRestaurant.ts +187 -0
  567. package/app/Models/realtime/Websocket.ts +77 -0
  568. package/app/Notifications/README.md +31 -0
  569. package/app/Notifications/Welcome.ts +32 -0
  570. package/app/Policies/PostPolicy.ts +131 -0
  571. package/app/README.md +23 -0
  572. package/app/Routes.ts +47 -0
  573. package/app/Scheduler.ts +28 -0
  574. package/app/Storefront/CartCookie.ts +109 -0
  575. 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
+ })