@btst/stack 2.3.0 → 2.5.0

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 (208) hide show
  1. package/dist/packages/stack/src/client/components/compose.cjs +1 -2
  2. package/dist/packages/stack/src/client/components/compose.mjs +1 -2
  3. package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.cjs +71 -0
  4. package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.mjs +68 -0
  5. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.cjs +87 -54
  6. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +87 -54
  7. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.cjs +2 -2
  8. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.mjs +2 -2
  9. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.cjs +89 -22
  10. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.mjs +90 -23
  11. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.cjs +110 -33
  12. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.mjs +112 -35
  13. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.cjs +1 -1
  14. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.mjs +1 -1
  15. package/dist/packages/stack/src/plugins/ai-chat/client/plugin.cjs +14 -21
  16. package/dist/packages/stack/src/plugins/ai-chat/client/plugin.mjs +15 -22
  17. package/dist/packages/stack/src/plugins/ai-chat/schemas.cjs +17 -1
  18. package/dist/packages/stack/src/plugins/ai-chat/schemas.mjs +17 -1
  19. package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +28 -45
  20. package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +22 -39
  21. package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.cjs +15 -2
  22. package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.mjs +16 -3
  23. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.cjs +24 -1
  24. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.mjs +24 -1
  25. package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.cjs +26 -0
  26. package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.mjs +24 -0
  27. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.cjs +30 -1
  28. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.mjs +30 -1
  29. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +18 -0
  30. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +18 -0
  31. package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +23 -27
  32. package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +24 -28
  33. package/dist/packages/stack/src/plugins/cms/api/mutations.cjs +48 -0
  34. package/dist/packages/stack/src/plugins/cms/api/mutations.mjs +46 -0
  35. package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +21 -18
  36. package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +21 -18
  37. package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +11 -15
  38. package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +12 -16
  39. package/dist/packages/stack/src/plugins/form-builder/api/plugin.cjs +58 -62
  40. package/dist/packages/stack/src/plugins/form-builder/api/plugin.mjs +58 -62
  41. package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +12 -12
  42. package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +13 -13
  43. package/dist/packages/stack/src/plugins/kanban/api/mutations.cjs +91 -0
  44. package/dist/packages/stack/src/plugins/kanban/api/mutations.mjs +87 -0
  45. package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +92 -118
  46. package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +89 -115
  47. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.cjs +7 -3
  48. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.mjs +7 -3
  49. package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +22 -29
  50. package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +23 -30
  51. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.cjs +89 -0
  52. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.mjs +89 -0
  53. package/dist/packages/stack/src/plugins/ui-builder/client/plugin.cjs +8 -8
  54. package/dist/packages/stack/src/plugins/ui-builder/client/plugin.mjs +9 -9
  55. package/dist/packages/stack/src/plugins/utils.cjs +42 -0
  56. package/dist/packages/stack/src/plugins/utils.mjs +41 -1
  57. package/dist/plugins/ai-chat/api/index.d.cts +1 -1
  58. package/dist/plugins/ai-chat/api/index.d.mts +1 -1
  59. package/dist/plugins/ai-chat/api/index.d.ts +1 -1
  60. package/dist/plugins/ai-chat/client/components/index.d.cts +1 -1
  61. package/dist/plugins/ai-chat/client/components/index.d.mts +1 -1
  62. package/dist/plugins/ai-chat/client/components/index.d.ts +1 -1
  63. package/dist/plugins/ai-chat/client/context/page-ai-context.cjs +92 -0
  64. package/dist/plugins/ai-chat/client/context/page-ai-context.d.cts +84 -0
  65. package/dist/plugins/ai-chat/client/context/page-ai-context.d.mts +84 -0
  66. package/dist/plugins/ai-chat/client/context/page-ai-context.d.ts +84 -0
  67. package/dist/plugins/ai-chat/client/context/page-ai-context.mjs +88 -0
  68. package/dist/plugins/ai-chat/client/hooks/index.d.cts +1 -1
  69. package/dist/plugins/ai-chat/client/hooks/index.d.mts +1 -1
  70. package/dist/plugins/ai-chat/client/hooks/index.d.ts +1 -1
  71. package/dist/plugins/ai-chat/client/index.d.cts +10 -10
  72. package/dist/plugins/ai-chat/client/index.d.mts +10 -10
  73. package/dist/plugins/ai-chat/client/index.d.ts +10 -10
  74. package/dist/plugins/ai-chat/query-keys.d.cts +1 -1
  75. package/dist/plugins/ai-chat/query-keys.d.mts +1 -1
  76. package/dist/plugins/ai-chat/query-keys.d.ts +1 -1
  77. package/dist/plugins/blog/api/index.d.cts +2 -2
  78. package/dist/plugins/blog/api/index.d.mts +2 -2
  79. package/dist/plugins/blog/api/index.d.ts +2 -2
  80. package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
  81. package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
  82. package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
  83. package/dist/plugins/blog/client/index.d.cts +13 -13
  84. package/dist/plugins/blog/client/index.d.mts +13 -13
  85. package/dist/plugins/blog/client/index.d.ts +13 -13
  86. package/dist/plugins/blog/query-keys.d.cts +2 -2
  87. package/dist/plugins/blog/query-keys.d.mts +2 -2
  88. package/dist/plugins/blog/query-keys.d.ts +2 -2
  89. package/dist/plugins/client/index.cjs +1 -0
  90. package/dist/plugins/client/index.d.cts +8 -1
  91. package/dist/plugins/client/index.d.mts +8 -1
  92. package/dist/plugins/client/index.d.ts +8 -1
  93. package/dist/plugins/client/index.mjs +1 -1
  94. package/dist/plugins/cms/api/index.cjs +2 -0
  95. package/dist/plugins/cms/api/index.d.cts +2 -2
  96. package/dist/plugins/cms/api/index.d.mts +2 -2
  97. package/dist/plugins/cms/api/index.d.ts +2 -2
  98. package/dist/plugins/cms/api/index.mjs +1 -0
  99. package/dist/plugins/cms/client/hooks/index.d.cts +1 -1
  100. package/dist/plugins/cms/client/hooks/index.d.mts +1 -1
  101. package/dist/plugins/cms/client/hooks/index.d.ts +1 -1
  102. package/dist/plugins/cms/client/index.d.cts +6 -6
  103. package/dist/plugins/cms/client/index.d.mts +6 -6
  104. package/dist/plugins/cms/client/index.d.ts +6 -6
  105. package/dist/plugins/cms/query-keys.d.cts +2 -2
  106. package/dist/plugins/cms/query-keys.d.mts +2 -2
  107. package/dist/plugins/cms/query-keys.d.ts +2 -2
  108. package/dist/plugins/form-builder/api/index.d.cts +2 -2
  109. package/dist/plugins/form-builder/api/index.d.mts +2 -2
  110. package/dist/plugins/form-builder/api/index.d.ts +2 -2
  111. package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
  112. package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
  113. package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
  114. package/dist/plugins/form-builder/client/hooks/index.d.cts +1 -1
  115. package/dist/plugins/form-builder/client/hooks/index.d.mts +1 -1
  116. package/dist/plugins/form-builder/client/hooks/index.d.ts +1 -1
  117. package/dist/plugins/form-builder/client/index.d.cts +6 -6
  118. package/dist/plugins/form-builder/client/index.d.mts +6 -6
  119. package/dist/plugins/form-builder/client/index.d.ts +6 -6
  120. package/dist/plugins/form-builder/query-keys.d.cts +2 -2
  121. package/dist/plugins/form-builder/query-keys.d.mts +2 -2
  122. package/dist/plugins/form-builder/query-keys.d.ts +2 -2
  123. package/dist/plugins/kanban/api/index.cjs +4 -0
  124. package/dist/plugins/kanban/api/index.d.cts +1 -1
  125. package/dist/plugins/kanban/api/index.d.mts +1 -1
  126. package/dist/plugins/kanban/api/index.d.ts +1 -1
  127. package/dist/plugins/kanban/api/index.mjs +1 -0
  128. package/dist/plugins/kanban/client/index.d.cts +12 -12
  129. package/dist/plugins/kanban/client/index.d.mts +12 -12
  130. package/dist/plugins/kanban/client/index.d.ts +12 -12
  131. package/dist/plugins/kanban/query-keys.d.cts +1 -1
  132. package/dist/plugins/kanban/query-keys.d.mts +1 -1
  133. package/dist/plugins/kanban/query-keys.d.ts +1 -1
  134. package/dist/plugins/ui-builder/client/hooks/index.d.cts +1 -1
  135. package/dist/plugins/ui-builder/client/hooks/index.d.mts +1 -1
  136. package/dist/plugins/ui-builder/client/hooks/index.d.ts +1 -1
  137. package/dist/plugins/ui-builder/client/index.d.cts +3 -3
  138. package/dist/plugins/ui-builder/client/index.d.mts +3 -3
  139. package/dist/plugins/ui-builder/client/index.d.ts +3 -3
  140. package/dist/plugins/ui-builder/index.d.cts +2 -2
  141. package/dist/plugins/ui-builder/index.d.mts +2 -2
  142. package/dist/plugins/ui-builder/index.d.ts +2 -2
  143. package/dist/shared/{stack.C-WUPMT6.d.cts → stack.B2xZTSiO.d.cts} +4 -4
  144. package/dist/shared/{stack.B1EeBt1b.d.ts → stack.B58oHdqm.d.mts} +33 -3
  145. package/dist/shared/{stack.CVDTkMoO.d.mts → stack.B8QD11QU.d.cts} +7 -7
  146. package/dist/shared/{stack.CVDTkMoO.d.cts → stack.B8QD11QU.d.mts} +7 -7
  147. package/dist/shared/{stack.CVDTkMoO.d.ts → stack.B8QD11QU.d.ts} +7 -7
  148. package/dist/shared/{stack.CIP6QS9l.d.ts → stack.BDVEpue1.d.ts} +1 -1
  149. package/dist/shared/{stack.C5dtIncc.d.mts → stack.BTvbxZvw.d.cts} +1 -1
  150. package/dist/shared/{stack.DaOcgmrM.d.ts → stack.BV9hnvu4.d.cts} +31 -7
  151. package/dist/shared/{stack.DaOcgmrM.d.cts → stack.BV9hnvu4.d.mts} +31 -7
  152. package/dist/shared/{stack.DaOcgmrM.d.mts → stack.BV9hnvu4.d.ts} +31 -7
  153. package/dist/shared/{stack.DdI5W6MB.d.mts → stack.BozPgbrZ.d.cts} +19 -19
  154. package/dist/shared/{stack.DdI5W6MB.d.ts → stack.BozPgbrZ.d.mts} +19 -19
  155. package/dist/shared/{stack.DdI5W6MB.d.cts → stack.BozPgbrZ.d.ts} +19 -19
  156. package/dist/shared/{stack.CP68pFEH.d.mts → stack.C9Mg2Q46.d.cts} +33 -3
  157. package/dist/shared/{stack.BeSm90va.d.ts → stack.CTDVxbrA.d.ts} +72 -14
  158. package/dist/shared/{stack.C-Ptrz8s.d.ts → stack.Cj_zKww4.d.ts} +4 -4
  159. package/dist/shared/{stack.TIBF2AOx.d.ts → stack.CxaFNQCV.d.mts} +89 -34
  160. package/dist/shared/{stack.CMh_EdxW.d.cts → stack.D-b5zbPm.d.cts} +72 -14
  161. package/dist/shared/{stack.Dw0Ly2TM.d.cts → stack.DTtmJPQO.d.mts} +1 -1
  162. package/dist/shared/{stack.BKfolAyK.d.ts → stack.DXnclTG7.d.ts} +11 -11
  163. package/dist/shared/{stack.snB1EDP7.d.cts → stack.DaZM10cp.d.cts} +11 -11
  164. package/dist/shared/{stack.Dg09R0oB.d.mts → stack.FVWf2JhZ.d.mts} +72 -14
  165. package/dist/shared/{stack.BIXEI6v_.d.mts → stack.cfCkioTe.d.mts} +11 -11
  166. package/dist/shared/{stack.6fUOjLs9.d.mts → stack.dH7u-TJH.d.mts} +4 -4
  167. package/dist/shared/{stack.BpolpQpf.d.cts → stack.j75TpKh2.d.ts} +89 -34
  168. package/dist/shared/{stack.rTy7-wQU.d.mts → stack.n1_i1p2B.d.cts} +89 -34
  169. package/dist/shared/{stack.IdtKDRka.d.cts → stack.sO33ZDhK.d.ts} +33 -3
  170. package/package.json +14 -1
  171. package/src/client/components/compose.tsx +7 -4
  172. package/src/plugins/ai-chat/api/page-tools.ts +111 -0
  173. package/src/plugins/ai-chat/api/plugin.ts +228 -72
  174. package/src/plugins/ai-chat/client/components/chat-input.tsx +2 -2
  175. package/src/plugins/ai-chat/client/components/chat-interface.tsx +154 -58
  176. package/src/plugins/ai-chat/client/components/chat-layout.tsx +166 -32
  177. package/src/plugins/ai-chat/client/components/chat-sidebar.tsx +1 -1
  178. package/src/plugins/ai-chat/client/context/page-ai-context.tsx +240 -0
  179. package/src/plugins/ai-chat/client/plugin.tsx +23 -31
  180. package/src/plugins/ai-chat/schemas.ts +16 -0
  181. package/src/plugins/blog/api/plugin.ts +31 -47
  182. package/src/plugins/blog/client/components/forms/post-forms.tsx +29 -2
  183. package/src/plugins/blog/client/components/pages/edit-post-page.internal.tsx +28 -0
  184. package/src/plugins/blog/client/components/pages/fill-blog-form-handler.ts +38 -0
  185. package/src/plugins/blog/client/components/pages/new-post-page.internal.tsx +33 -1
  186. package/src/plugins/blog/client/components/pages/post-page.internal.tsx +20 -0
  187. package/src/plugins/blog/client/plugin.tsx +36 -39
  188. package/src/plugins/client/index.ts +5 -1
  189. package/src/plugins/cms/api/index.ts +4 -0
  190. package/src/plugins/cms/api/mutations.ts +84 -0
  191. package/src/plugins/cms/api/plugin.ts +23 -17
  192. package/src/plugins/cms/client/plugin.tsx +18 -21
  193. package/src/plugins/cms/types.ts +7 -7
  194. package/src/plugins/form-builder/api/plugin.ts +64 -64
  195. package/src/plugins/form-builder/client/plugin.tsx +19 -18
  196. package/src/plugins/form-builder/types.ts +19 -24
  197. package/src/plugins/kanban/api/index.ts +6 -0
  198. package/src/plugins/kanban/api/mutations.ts +169 -0
  199. package/src/plugins/kanban/api/plugin.ts +123 -136
  200. package/src/plugins/kanban/client/hooks/kanban-hooks.tsx +4 -0
  201. package/src/plugins/kanban/client/plugin.tsx +35 -41
  202. package/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.tsx +132 -0
  203. package/src/plugins/ui-builder/client/plugin.tsx +11 -10
  204. package/src/plugins/ui-builder/types.ts +4 -4
  205. package/src/plugins/utils.ts +92 -1
  206. package/dist/shared/{stack.CBON0dWL.d.mts → stack.BQmuNl5p.d.cts} +2 -2
  207. package/dist/shared/{stack.CBON0dWL.d.ts → stack.BQmuNl5p.d.mts} +2 -2
  208. package/dist/shared/{stack.CBON0dWL.d.cts → stack.BQmuNl5p.d.ts} +2 -2
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { C as ContentTypeConfig } from '../../shared/stack.CVDTkMoO.mjs';
3
- export { L as LoaderContext, b as PaginatedUIBuilderPages, P as ParsedUIBuilderPage, S as SerializedUIBuilderPage, c as UIBuilderClientHooks, a as UIBuilderPage, U as UIBuilderPageData } from '../../shared/stack.6fUOjLs9.mjs';
2
+ import { C as ContentTypeConfig } from '../../shared/stack.B8QD11QU.mjs';
3
+ export { L as LoaderContext, b as PaginatedUIBuilderPages, P as ParsedUIBuilderPage, S as SerializedUIBuilderPage, c as UIBuilderClientHooks, a as UIBuilderPage, U as UIBuilderPageData } from '../../shared/stack.dH7u-TJH.mjs';
4
4
  export { C as ComponentLayer, a as ComponentRegistry, R as RegistryEntry, V as Variable } from '../../shared/stack.D1DMlJp-.mjs';
5
5
  import 'react';
6
6
  import '../../shared/stack.8nldKomx.mjs';
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { C as ContentTypeConfig } from '../../shared/stack.CVDTkMoO.js';
3
- export { L as LoaderContext, b as PaginatedUIBuilderPages, P as ParsedUIBuilderPage, S as SerializedUIBuilderPage, c as UIBuilderClientHooks, a as UIBuilderPage, U as UIBuilderPageData } from '../../shared/stack.C-Ptrz8s.js';
2
+ import { C as ContentTypeConfig } from '../../shared/stack.B8QD11QU.js';
3
+ export { L as LoaderContext, b as PaginatedUIBuilderPages, P as ParsedUIBuilderPage, S as SerializedUIBuilderPage, c as UIBuilderClientHooks, a as UIBuilderPage, U as UIBuilderPageData } from '../../shared/stack.Cj_zKww4.js';
4
4
  export { C as ComponentLayer, a as ComponentRegistry, R as RegistryEntry, V as Variable } from '../../shared/stack.GygI_T3X.js';
5
5
  import 'react';
6
6
  import '../../shared/stack.8nldKomx.js';
@@ -83,21 +83,21 @@ interface LoaderContext {
83
83
  */
84
84
  interface UIBuilderClientHooks {
85
85
  /**
86
- * Called before loading the page list. Return false to cancel loading.
86
+ * Called before loading the page list. Throw an error to cancel loading.
87
87
  * @param context - Loader context with path, params, etc.
88
88
  */
89
- beforeLoadPageList?: (context: LoaderContext) => Promise<boolean> | boolean;
89
+ beforeLoadPageList?: (context: LoaderContext) => Promise<void> | void;
90
90
  /**
91
91
  * Called after the page list is loaded.
92
92
  * @param context - Loader context
93
93
  */
94
94
  afterLoadPageList?: (context: LoaderContext) => Promise<void> | void;
95
95
  /**
96
- * Called before loading the page builder. Return false to cancel loading.
96
+ * Called before loading the page builder. Throw an error to cancel loading.
97
97
  * @param pageId - The page ID (undefined for new pages)
98
98
  * @param context - Loader context
99
99
  */
100
- beforeLoadPageBuilder?: (pageId: string | undefined, context: LoaderContext) => Promise<boolean> | boolean;
100
+ beforeLoadPageBuilder?: (pageId: string | undefined, context: LoaderContext) => Promise<void> | void;
101
101
  /**
102
102
  * Called after the page builder is loaded.
103
103
  * @param pageId - The page ID (undefined for new pages)
@@ -1,5 +1,5 @@
1
1
  import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
2
- import { a as SerializedContentItemWithType, S as SerializedContentType, b as ContentType, c as ContentItem, d as SerializedContentItem, e as ContentItemWithType, f as CMSBackendConfig, I as InverseRelation } from './stack.CVDTkMoO.js';
2
+ import { a as SerializedContentItemWithType, S as SerializedContentType, b as ContentType, c as ContentItem, d as SerializedContentItem, e as ContentItemWithType, f as CMSBackendConfig, I as InverseRelation } from './stack.B8QD11QU.mjs';
3
3
  import * as better_call from 'better-call';
4
4
  import { z } from 'zod';
5
5
  import { Adapter } from '@btst/db';
@@ -78,6 +78,35 @@ declare function getContentItemById(adapter: Adapter, id: string): Promise<Seria
78
78
  */
79
79
  declare function getContentItemBySlug(adapter: Adapter, contentTypeSlug: string, slug: string): Promise<SerializedContentItemWithType | null>;
80
80
 
81
+ /**
82
+ * Input for creating a new CMS content item.
83
+ */
84
+ interface CreateCMSContentItemInput {
85
+ /** URL-safe slug for the item */
86
+ slug: string;
87
+ /** Arbitrary data payload — should match the content type schema */
88
+ data: Record<string, unknown>;
89
+ }
90
+ /**
91
+ * Create a new content item for a content type (looked up by slug).
92
+ *
93
+ * Bypasses Zod schema validation and relation processing — the caller is
94
+ * responsible for providing valid, relation-free data. For relation fields or
95
+ * schema validation, use the HTTP endpoint instead.
96
+ *
97
+ * Throws if the content type is not found or the slug is already taken within
98
+ * that content type.
99
+ *
100
+ * @remarks **Security:** No authorization hooks (`onBeforeCreate`, `onAfterCreate`)
101
+ * are called. The caller is responsible for any access-control checks before
102
+ * invoking this function.
103
+ *
104
+ * @param adapter - The database adapter
105
+ * @param contentTypeSlug - Slug of the target content type
106
+ * @param input - Item slug and data payload
107
+ */
108
+ declare function createCMSContentItem(adapter: Adapter, contentTypeSlug: string, input: CreateCMSContentItemInput): Promise<SerializedContentItem>;
109
+
81
110
  /**
82
111
  * Route keys for the CMS plugin — matches the keys returned by
83
112
  * `stackClient.router.getRoute(path).routeKey`.
@@ -257,6 +286,7 @@ declare const cmsBackendPlugin: (config: CMSBackendConfig) => _btst_stack_plugin
257
286
  getContentItemBySlug: (contentTypeSlug: string, slug: string) => Promise<SerializedContentItemWithType<Record<string, unknown>> | null>;
258
287
  getContentItemById: (id: string) => Promise<SerializedContentItemWithType<Record<string, unknown>> | null>;
259
288
  prefetchForRoute: CMSPrefetchForRoute;
289
+ createContentItem: (typeSlug: string, input: Parameters<typeof createCMSContentItem>[2]) => Promise<SerializedContentItem>;
260
290
  }>;
261
291
  type CMSApiRouter = ReturnType<ReturnType<typeof cmsBackendPlugin>["routes"]>;
262
292
 
@@ -293,5 +323,5 @@ declare const CMS_QUERY_KEYS: {
293
323
  contentDetail: (typeSlug: string, id: string) => readonly ["cmsContent", "detail", string, string];
294
324
  };
295
325
 
296
- export { cmsBackendPlugin as c, getAllContentItems as d, getContentItemBySlug as e, getContentItemById as f, getAllContentTypes as g, serializeContentItem as h, serializeContentItemWithType as i, CMS_QUERY_KEYS as j, serializeContentType as s };
297
- export type { CMSApiRouter as C, ContentListDiscriminator as a, CMSRouteKey as b };
326
+ export { cmsBackendPlugin as c, getAllContentItems as d, getContentItemBySlug as e, getContentItemById as f, getAllContentTypes as g, serializeContentItem as h, serializeContentItemWithType as i, createCMSContentItem as j, CMS_QUERY_KEYS as l, serializeContentType as s };
327
+ export type { CMSApiRouter as C, ContentListDiscriminator as a, CMSRouteKey as b, CreateCMSContentItemInput as k };
@@ -130,21 +130,21 @@ interface CMSHookContext {
130
130
  /**
131
131
  * Hooks for customizing CMS backend behavior
132
132
  *
133
- * Note: Before hooks can only deny operations by returning `false`.
133
+ * Note: Before hooks deny operations by throwing an error.
134
134
  * They cannot modify the data being saved. This ensures consistency
135
135
  * between the stored content item data and relation junction tables.
136
136
  */
137
137
  interface CMSBackendHooks {
138
- /** Called before creating a content item. Return false to deny the operation. */
139
- onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
138
+ /** Called before creating a content item. Throw an error to deny the operation. */
139
+ onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<void> | void;
140
140
  /** Called after creating a content item */
141
141
  onAfterCreate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
142
- /** Called before updating a content item. Return false to deny the operation. */
143
- onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
142
+ /** Called before updating a content item. Throw an error to deny the operation. */
143
+ onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<void> | void;
144
144
  /** Called after updating a content item */
145
145
  onAfterUpdate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
146
- /** Called before deleting a content item */
147
- onBeforeDelete?: (id: string, context: CMSHookContext) => Promise<boolean> | boolean;
146
+ /** Called before deleting a content item. Throw an error to deny the operation. */
147
+ onBeforeDelete?: (id: string, context: CMSHookContext) => Promise<void> | void;
148
148
  /** Called after deleting a content item */
149
149
  onAfterDelete?: (id: string, context: CMSHookContext) => Promise<void> | void;
150
150
  /** Called on any CMS error */
@@ -130,21 +130,21 @@ interface CMSHookContext {
130
130
  /**
131
131
  * Hooks for customizing CMS backend behavior
132
132
  *
133
- * Note: Before hooks can only deny operations by returning `false`.
133
+ * Note: Before hooks deny operations by throwing an error.
134
134
  * They cannot modify the data being saved. This ensures consistency
135
135
  * between the stored content item data and relation junction tables.
136
136
  */
137
137
  interface CMSBackendHooks {
138
- /** Called before creating a content item. Return false to deny the operation. */
139
- onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
138
+ /** Called before creating a content item. Throw an error to deny the operation. */
139
+ onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<void> | void;
140
140
  /** Called after creating a content item */
141
141
  onAfterCreate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
142
- /** Called before updating a content item. Return false to deny the operation. */
143
- onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
142
+ /** Called before updating a content item. Throw an error to deny the operation. */
143
+ onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<void> | void;
144
144
  /** Called after updating a content item */
145
145
  onAfterUpdate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
146
- /** Called before deleting a content item */
147
- onBeforeDelete?: (id: string, context: CMSHookContext) => Promise<boolean> | boolean;
146
+ /** Called before deleting a content item. Throw an error to deny the operation. */
147
+ onBeforeDelete?: (id: string, context: CMSHookContext) => Promise<void> | void;
148
148
  /** Called after deleting a content item */
149
149
  onAfterDelete?: (id: string, context: CMSHookContext) => Promise<void> | void;
150
150
  /** Called on any CMS error */
@@ -130,21 +130,21 @@ interface CMSHookContext {
130
130
  /**
131
131
  * Hooks for customizing CMS backend behavior
132
132
  *
133
- * Note: Before hooks can only deny operations by returning `false`.
133
+ * Note: Before hooks deny operations by throwing an error.
134
134
  * They cannot modify the data being saved. This ensures consistency
135
135
  * between the stored content item data and relation junction tables.
136
136
  */
137
137
  interface CMSBackendHooks {
138
- /** Called before creating a content item. Return false to deny the operation. */
139
- onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
138
+ /** Called before creating a content item. Throw an error to deny the operation. */
139
+ onBeforeCreate?: (data: Record<string, unknown>, context: CMSHookContext) => Promise<void> | void;
140
140
  /** Called after creating a content item */
141
141
  onAfterCreate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
142
- /** Called before updating a content item. Return false to deny the operation. */
143
- onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<false | void> | false | void;
142
+ /** Called before updating a content item. Throw an error to deny the operation. */
143
+ onBeforeUpdate?: (id: string, data: Record<string, unknown>, context: CMSHookContext) => Promise<void> | void;
144
144
  /** Called after updating a content item */
145
145
  onAfterUpdate?: (item: SerializedContentItem, context: CMSHookContext) => Promise<void> | void;
146
- /** Called before deleting a content item */
147
- onBeforeDelete?: (id: string, context: CMSHookContext) => Promise<boolean> | boolean;
146
+ /** Called before deleting a content item. Throw an error to deny the operation. */
147
+ onBeforeDelete?: (id: string, context: CMSHookContext) => Promise<void> | void;
148
148
  /** Called after deleting a content item */
149
149
  onAfterDelete?: (id: string, context: CMSHookContext) => Promise<void> | void;
150
150
  /** Called on any CMS error */
@@ -1,6 +1,6 @@
1
1
  import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
2
2
  import * as better_call from 'better-call';
3
- import { S as SerializedForm, b as SerializedFormSubmissionWithData, F as Form, d as FormSubmission, a as SerializedFormSubmission, e as FormSubmissionWithForm, f as FormBuilderBackendConfig } from './stack.DdI5W6MB.js';
3
+ import { S as SerializedForm, b as SerializedFormSubmissionWithData, F as Form, d as FormSubmission, a as SerializedFormSubmission, e as FormSubmissionWithForm, f as FormBuilderBackendConfig } from './stack.BozPgbrZ.js';
4
4
  import { z } from 'zod';
5
5
  import { Adapter } from '@btst/db';
6
6
  import { QueryClient } from '@tanstack/react-query';
@@ -1,6 +1,6 @@
1
1
  import * as _btst_stack_plugins_api from '@btst/stack/plugins/api';
2
2
  import * as better_call from 'better-call';
3
- import { S as SerializedForm, b as SerializedFormSubmissionWithData, F as Form, d as FormSubmission, a as SerializedFormSubmission, e as FormSubmissionWithForm, f as FormBuilderBackendConfig } from './stack.DdI5W6MB.mjs';
3
+ import { S as SerializedForm, b as SerializedFormSubmissionWithData, F as Form, d as FormSubmission, a as SerializedFormSubmission, e as FormSubmissionWithForm, f as FormBuilderBackendConfig } from './stack.BozPgbrZ.cjs';
4
4
  import { z } from 'zod';
5
5
  import { Adapter } from '@btst/db';
6
6
  import { QueryClient } from '@tanstack/react-query';
@@ -244,31 +244,55 @@ interface ChatInterfaceProps {
244
244
  }
245
245
  declare function ChatInterface({ apiPath, initialMessages, id, variant, className, onMessagesChange, }: ChatInterfaceProps): react_jsx_runtime.JSX.Element;
246
246
 
247
- interface ChatLayoutProps {
247
+ interface ChatLayoutBaseProps {
248
248
  /** API base URL */
249
249
  apiBaseURL: string;
250
250
  /** API base path */
251
251
  apiBasePath: string;
252
252
  /** Current conversation ID (if viewing existing conversation) */
253
253
  conversationId?: string;
254
- /** Layout mode: 'full' for full page with sidebar, 'widget' for embeddable widget */
255
- layout?: "full" | "widget";
256
254
  /** Additional class name for the container */
257
255
  className?: string;
258
- /** Whether to show the sidebar (default: true for full layout) */
256
+ /** Whether to show the sidebar */
259
257
  showSidebar?: boolean;
260
- /** Height of the widget (only applies to widget layout) */
261
- widgetHeight?: string | number;
262
258
  /** Initial messages to populate the chat (useful for localStorage persistence in public mode) */
263
259
  initialMessages?: UIMessage[];
264
260
  /** Called whenever messages change (for persistence). Only fires in public mode. */
265
261
  onMessagesChange?: (messages: UIMessage[]) => void;
266
262
  }
263
+ interface ChatLayoutWidgetProps extends ChatLayoutBaseProps {
264
+ /** Widget mode: compact embeddable panel with a floating trigger button */
265
+ layout: "widget";
266
+ /** Height of the widget panel. Default: `"600px"` */
267
+ widgetHeight?: string | number;
268
+ /** Width of the widget panel. Default: `"380px"` */
269
+ widgetWidth?: string | number;
270
+ /**
271
+ * Whether the widget panel starts open. Default: `false`.
272
+ * Set to `true` when embedding inside an already-open container such as a
273
+ * Next.js intercepting-route modal — the panel will be immediately visible
274
+ * without the user needing to click the trigger button.
275
+ */
276
+ defaultOpen?: boolean;
277
+ /**
278
+ * Whether to render the built-in floating trigger button. Default: `true`.
279
+ * Set to `false` when you control open/close externally (e.g. a Next.js
280
+ * parallel-route slot, a custom button, or a `router.back()` dismiss action)
281
+ * so that the built-in button does not appear alongside your own UI.
282
+ */
283
+ showTrigger?: boolean;
284
+ }
285
+ interface ChatLayoutFullProps extends ChatLayoutBaseProps {
286
+ /** Full-page mode with sidebar navigation (default) */
287
+ layout?: "full";
288
+ }
289
+ /** Props for the ChatLayout component */
290
+ type ChatLayoutProps = ChatLayoutWidgetProps | ChatLayoutFullProps;
267
291
  /**
268
292
  * ChatLayout component that provides a full-page chat experience with sidebar
269
293
  * or a compact widget mode for embedding.
270
294
  */
271
- declare function ChatLayout({ apiBaseURL, apiBasePath, conversationId, layout, className, showSidebar, widgetHeight, initialMessages, onMessagesChange, }: ChatLayoutProps): react_jsx_runtime.JSX.Element;
295
+ declare function ChatLayout(props: ChatLayoutProps): react_jsx_runtime.JSX.Element;
272
296
 
273
297
  interface ChatSidebarProps {
274
298
  currentConversationId?: string;
@@ -244,31 +244,55 @@ interface ChatInterfaceProps {
244
244
  }
245
245
  declare function ChatInterface({ apiPath, initialMessages, id, variant, className, onMessagesChange, }: ChatInterfaceProps): react_jsx_runtime.JSX.Element;
246
246
 
247
- interface ChatLayoutProps {
247
+ interface ChatLayoutBaseProps {
248
248
  /** API base URL */
249
249
  apiBaseURL: string;
250
250
  /** API base path */
251
251
  apiBasePath: string;
252
252
  /** Current conversation ID (if viewing existing conversation) */
253
253
  conversationId?: string;
254
- /** Layout mode: 'full' for full page with sidebar, 'widget' for embeddable widget */
255
- layout?: "full" | "widget";
256
254
  /** Additional class name for the container */
257
255
  className?: string;
258
- /** Whether to show the sidebar (default: true for full layout) */
256
+ /** Whether to show the sidebar */
259
257
  showSidebar?: boolean;
260
- /** Height of the widget (only applies to widget layout) */
261
- widgetHeight?: string | number;
262
258
  /** Initial messages to populate the chat (useful for localStorage persistence in public mode) */
263
259
  initialMessages?: UIMessage[];
264
260
  /** Called whenever messages change (for persistence). Only fires in public mode. */
265
261
  onMessagesChange?: (messages: UIMessage[]) => void;
266
262
  }
263
+ interface ChatLayoutWidgetProps extends ChatLayoutBaseProps {
264
+ /** Widget mode: compact embeddable panel with a floating trigger button */
265
+ layout: "widget";
266
+ /** Height of the widget panel. Default: `"600px"` */
267
+ widgetHeight?: string | number;
268
+ /** Width of the widget panel. Default: `"380px"` */
269
+ widgetWidth?: string | number;
270
+ /**
271
+ * Whether the widget panel starts open. Default: `false`.
272
+ * Set to `true` when embedding inside an already-open container such as a
273
+ * Next.js intercepting-route modal — the panel will be immediately visible
274
+ * without the user needing to click the trigger button.
275
+ */
276
+ defaultOpen?: boolean;
277
+ /**
278
+ * Whether to render the built-in floating trigger button. Default: `true`.
279
+ * Set to `false` when you control open/close externally (e.g. a Next.js
280
+ * parallel-route slot, a custom button, or a `router.back()` dismiss action)
281
+ * so that the built-in button does not appear alongside your own UI.
282
+ */
283
+ showTrigger?: boolean;
284
+ }
285
+ interface ChatLayoutFullProps extends ChatLayoutBaseProps {
286
+ /** Full-page mode with sidebar navigation (default) */
287
+ layout?: "full";
288
+ }
289
+ /** Props for the ChatLayout component */
290
+ type ChatLayoutProps = ChatLayoutWidgetProps | ChatLayoutFullProps;
267
291
  /**
268
292
  * ChatLayout component that provides a full-page chat experience with sidebar
269
293
  * or a compact widget mode for embedding.
270
294
  */
271
- declare function ChatLayout({ apiBaseURL, apiBasePath, conversationId, layout, className, showSidebar, widgetHeight, initialMessages, onMessagesChange, }: ChatLayoutProps): react_jsx_runtime.JSX.Element;
295
+ declare function ChatLayout(props: ChatLayoutProps): react_jsx_runtime.JSX.Element;
272
296
 
273
297
  interface ChatSidebarProps {
274
298
  currentConversationId?: string;
@@ -244,31 +244,55 @@ interface ChatInterfaceProps {
244
244
  }
245
245
  declare function ChatInterface({ apiPath, initialMessages, id, variant, className, onMessagesChange, }: ChatInterfaceProps): react_jsx_runtime.JSX.Element;
246
246
 
247
- interface ChatLayoutProps {
247
+ interface ChatLayoutBaseProps {
248
248
  /** API base URL */
249
249
  apiBaseURL: string;
250
250
  /** API base path */
251
251
  apiBasePath: string;
252
252
  /** Current conversation ID (if viewing existing conversation) */
253
253
  conversationId?: string;
254
- /** Layout mode: 'full' for full page with sidebar, 'widget' for embeddable widget */
255
- layout?: "full" | "widget";
256
254
  /** Additional class name for the container */
257
255
  className?: string;
258
- /** Whether to show the sidebar (default: true for full layout) */
256
+ /** Whether to show the sidebar */
259
257
  showSidebar?: boolean;
260
- /** Height of the widget (only applies to widget layout) */
261
- widgetHeight?: string | number;
262
258
  /** Initial messages to populate the chat (useful for localStorage persistence in public mode) */
263
259
  initialMessages?: UIMessage[];
264
260
  /** Called whenever messages change (for persistence). Only fires in public mode. */
265
261
  onMessagesChange?: (messages: UIMessage[]) => void;
266
262
  }
263
+ interface ChatLayoutWidgetProps extends ChatLayoutBaseProps {
264
+ /** Widget mode: compact embeddable panel with a floating trigger button */
265
+ layout: "widget";
266
+ /** Height of the widget panel. Default: `"600px"` */
267
+ widgetHeight?: string | number;
268
+ /** Width of the widget panel. Default: `"380px"` */
269
+ widgetWidth?: string | number;
270
+ /**
271
+ * Whether the widget panel starts open. Default: `false`.
272
+ * Set to `true` when embedding inside an already-open container such as a
273
+ * Next.js intercepting-route modal — the panel will be immediately visible
274
+ * without the user needing to click the trigger button.
275
+ */
276
+ defaultOpen?: boolean;
277
+ /**
278
+ * Whether to render the built-in floating trigger button. Default: `true`.
279
+ * Set to `false` when you control open/close externally (e.g. a Next.js
280
+ * parallel-route slot, a custom button, or a `router.back()` dismiss action)
281
+ * so that the built-in button does not appear alongside your own UI.
282
+ */
283
+ showTrigger?: boolean;
284
+ }
285
+ interface ChatLayoutFullProps extends ChatLayoutBaseProps {
286
+ /** Full-page mode with sidebar navigation (default) */
287
+ layout?: "full";
288
+ }
289
+ /** Props for the ChatLayout component */
290
+ type ChatLayoutProps = ChatLayoutWidgetProps | ChatLayoutFullProps;
267
291
  /**
268
292
  * ChatLayout component that provides a full-page chat experience with sidebar
269
293
  * or a compact widget mode for embedding.
270
294
  */
271
- declare function ChatLayout({ apiBaseURL, apiBasePath, conversationId, layout, className, showSidebar, widgetHeight, initialMessages, onMessagesChange, }: ChatLayoutProps): react_jsx_runtime.JSX.Element;
295
+ declare function ChatLayout(props: ChatLayoutProps): react_jsx_runtime.JSX.Element;
272
296
 
273
297
  interface ChatSidebarProps {
274
298
  currentConversationId?: string;
@@ -146,32 +146,32 @@ interface FormUpdate {
146
146
  * Backend hooks for Form Builder plugin
147
147
  *
148
148
  * All CRUD hooks receive ipAddress and headers for auth/rate limiting.
149
- * Return false from onBefore* hooks to reject the operation (throws 403).
149
+ * Throw an error from onBefore* hooks to reject the operation (throws 403).
150
150
  */
151
151
  interface FormBuilderBackendHooks {
152
- /** Called before listing forms. Return false to deny access (403). */
153
- onBeforeListForms?: (ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
154
- /** Called before creating a form. Return false to deny, or modified data. */
155
- onBeforeFormCreated?: (data: FormInput, ctx: FormBuilderHookContext) => Promise<FormInput | false> | FormInput | false;
152
+ /** Called before listing forms. Throw an error to deny access (403). */
153
+ onBeforeListForms?: (ctx: FormBuilderHookContext) => Promise<void> | void;
154
+ /** Called before creating a form. Throw an error to deny, or return modified data. */
155
+ onBeforeFormCreated?: (data: FormInput, ctx: FormBuilderHookContext) => Promise<FormInput | void> | FormInput | void;
156
156
  /** Called after a form is created */
157
157
  onAfterFormCreated?: (form: SerializedForm, ctx: FormBuilderHookContext) => Promise<void> | void;
158
- /** Called before getting a form by ID or slug. Return false to deny access. */
159
- onBeforeGetForm?: (idOrSlug: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
160
- /** Called before updating a form. Return false to deny, or modified data. */
161
- onBeforeFormUpdated?: (id: string, data: FormUpdate, ctx: FormBuilderHookContext) => Promise<FormUpdate | false> | FormUpdate | false;
158
+ /** Called before getting a form by ID or slug. Throw an error to deny access. */
159
+ onBeforeGetForm?: (idOrSlug: string, ctx: FormBuilderHookContext) => Promise<void> | void;
160
+ /** Called before updating a form. Throw an error to deny, or return modified data. */
161
+ onBeforeFormUpdated?: (id: string, data: FormUpdate, ctx: FormBuilderHookContext) => Promise<FormUpdate | void> | FormUpdate | void;
162
162
  /** Called after a form is updated */
163
163
  onAfterFormUpdated?: (form: SerializedForm, ctx: FormBuilderHookContext) => Promise<void> | void;
164
- /** Called before deleting a form. Return false to deny. */
165
- onBeforeFormDeleted?: (id: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
164
+ /** Called before deleting a form. Throw an error to deny. */
165
+ onBeforeFormDeleted?: (id: string, ctx: FormBuilderHookContext) => Promise<void> | void;
166
166
  /** Called after a form is deleted */
167
167
  onAfterFormDeleted?: (id: string, ctx: FormBuilderHookContext) => Promise<void> | void;
168
168
  /**
169
169
  * Called before processing a form submission.
170
170
  * Use for: spam protection, rate limiting, data validation/enrichment.
171
171
  *
172
- * @returns false to reject submission (400), or modified data to continue
172
+ * Throw an error to reject submission (400), or return modified data to continue.
173
173
  */
174
- onBeforeSubmission?: (formSlug: string, data: Record<string, unknown>, ctx: SubmissionHookContext) => Promise<Record<string, unknown> | false> | Record<string, unknown> | false;
174
+ onBeforeSubmission?: (formSlug: string, data: Record<string, unknown>, ctx: SubmissionHookContext) => Promise<Record<string, unknown> | void> | Record<string, unknown> | void;
175
175
  /**
176
176
  * Called after a submission is saved.
177
177
  * Use for: sending emails, storing in CRM, triggering workflows.
@@ -179,12 +179,12 @@ interface FormBuilderBackendHooks {
179
179
  onAfterSubmission?: (submission: SerializedFormSubmission, form: SerializedForm, ctx: SubmissionHookContext) => Promise<void> | void;
180
180
  /** Called when a submission fails */
181
181
  onSubmissionError?: (error: Error, formSlug: string, data: Record<string, unknown>, ctx: SubmissionHookContext) => Promise<void> | void;
182
- /** Called before listing submissions. Return false to deny access (403). */
183
- onBeforeListSubmissions?: (formId: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
184
- /** Called before getting a submission. Return false to deny access. */
185
- onBeforeGetSubmission?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
186
- /** Called before deleting a submission. Return false to deny. */
187
- onBeforeSubmissionDeleted?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
182
+ /** Called before listing submissions. Throw an error to deny access (403). */
183
+ onBeforeListSubmissions?: (formId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
184
+ /** Called before getting a submission. Throw an error to deny access. */
185
+ onBeforeGetSubmission?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
186
+ /** Called before deleting a submission. Throw an error to deny. */
187
+ onBeforeSubmissionDeleted?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
188
188
  /** Called after a submission is deleted */
189
189
  onAfterSubmissionDeleted?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
190
190
  /** Called on any error */
@@ -146,32 +146,32 @@ interface FormUpdate {
146
146
  * Backend hooks for Form Builder plugin
147
147
  *
148
148
  * All CRUD hooks receive ipAddress and headers for auth/rate limiting.
149
- * Return false from onBefore* hooks to reject the operation (throws 403).
149
+ * Throw an error from onBefore* hooks to reject the operation (throws 403).
150
150
  */
151
151
  interface FormBuilderBackendHooks {
152
- /** Called before listing forms. Return false to deny access (403). */
153
- onBeforeListForms?: (ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
154
- /** Called before creating a form. Return false to deny, or modified data. */
155
- onBeforeFormCreated?: (data: FormInput, ctx: FormBuilderHookContext) => Promise<FormInput | false> | FormInput | false;
152
+ /** Called before listing forms. Throw an error to deny access (403). */
153
+ onBeforeListForms?: (ctx: FormBuilderHookContext) => Promise<void> | void;
154
+ /** Called before creating a form. Throw an error to deny, or return modified data. */
155
+ onBeforeFormCreated?: (data: FormInput, ctx: FormBuilderHookContext) => Promise<FormInput | void> | FormInput | void;
156
156
  /** Called after a form is created */
157
157
  onAfterFormCreated?: (form: SerializedForm, ctx: FormBuilderHookContext) => Promise<void> | void;
158
- /** Called before getting a form by ID or slug. Return false to deny access. */
159
- onBeforeGetForm?: (idOrSlug: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
160
- /** Called before updating a form. Return false to deny, or modified data. */
161
- onBeforeFormUpdated?: (id: string, data: FormUpdate, ctx: FormBuilderHookContext) => Promise<FormUpdate | false> | FormUpdate | false;
158
+ /** Called before getting a form by ID or slug. Throw an error to deny access. */
159
+ onBeforeGetForm?: (idOrSlug: string, ctx: FormBuilderHookContext) => Promise<void> | void;
160
+ /** Called before updating a form. Throw an error to deny, or return modified data. */
161
+ onBeforeFormUpdated?: (id: string, data: FormUpdate, ctx: FormBuilderHookContext) => Promise<FormUpdate | void> | FormUpdate | void;
162
162
  /** Called after a form is updated */
163
163
  onAfterFormUpdated?: (form: SerializedForm, ctx: FormBuilderHookContext) => Promise<void> | void;
164
- /** Called before deleting a form. Return false to deny. */
165
- onBeforeFormDeleted?: (id: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
164
+ /** Called before deleting a form. Throw an error to deny. */
165
+ onBeforeFormDeleted?: (id: string, ctx: FormBuilderHookContext) => Promise<void> | void;
166
166
  /** Called after a form is deleted */
167
167
  onAfterFormDeleted?: (id: string, ctx: FormBuilderHookContext) => Promise<void> | void;
168
168
  /**
169
169
  * Called before processing a form submission.
170
170
  * Use for: spam protection, rate limiting, data validation/enrichment.
171
171
  *
172
- * @returns false to reject submission (400), or modified data to continue
172
+ * Throw an error to reject submission (400), or return modified data to continue.
173
173
  */
174
- onBeforeSubmission?: (formSlug: string, data: Record<string, unknown>, ctx: SubmissionHookContext) => Promise<Record<string, unknown> | false> | Record<string, unknown> | false;
174
+ onBeforeSubmission?: (formSlug: string, data: Record<string, unknown>, ctx: SubmissionHookContext) => Promise<Record<string, unknown> | void> | Record<string, unknown> | void;
175
175
  /**
176
176
  * Called after a submission is saved.
177
177
  * Use for: sending emails, storing in CRM, triggering workflows.
@@ -179,12 +179,12 @@ interface FormBuilderBackendHooks {
179
179
  onAfterSubmission?: (submission: SerializedFormSubmission, form: SerializedForm, ctx: SubmissionHookContext) => Promise<void> | void;
180
180
  /** Called when a submission fails */
181
181
  onSubmissionError?: (error: Error, formSlug: string, data: Record<string, unknown>, ctx: SubmissionHookContext) => Promise<void> | void;
182
- /** Called before listing submissions. Return false to deny access (403). */
183
- onBeforeListSubmissions?: (formId: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
184
- /** Called before getting a submission. Return false to deny access. */
185
- onBeforeGetSubmission?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
186
- /** Called before deleting a submission. Return false to deny. */
187
- onBeforeSubmissionDeleted?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
182
+ /** Called before listing submissions. Throw an error to deny access (403). */
183
+ onBeforeListSubmissions?: (formId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
184
+ /** Called before getting a submission. Throw an error to deny access. */
185
+ onBeforeGetSubmission?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
186
+ /** Called before deleting a submission. Throw an error to deny. */
187
+ onBeforeSubmissionDeleted?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
188
188
  /** Called after a submission is deleted */
189
189
  onAfterSubmissionDeleted?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
190
190
  /** Called on any error */
@@ -146,32 +146,32 @@ interface FormUpdate {
146
146
  * Backend hooks for Form Builder plugin
147
147
  *
148
148
  * All CRUD hooks receive ipAddress and headers for auth/rate limiting.
149
- * Return false from onBefore* hooks to reject the operation (throws 403).
149
+ * Throw an error from onBefore* hooks to reject the operation (throws 403).
150
150
  */
151
151
  interface FormBuilderBackendHooks {
152
- /** Called before listing forms. Return false to deny access (403). */
153
- onBeforeListForms?: (ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
154
- /** Called before creating a form. Return false to deny, or modified data. */
155
- onBeforeFormCreated?: (data: FormInput, ctx: FormBuilderHookContext) => Promise<FormInput | false> | FormInput | false;
152
+ /** Called before listing forms. Throw an error to deny access (403). */
153
+ onBeforeListForms?: (ctx: FormBuilderHookContext) => Promise<void> | void;
154
+ /** Called before creating a form. Throw an error to deny, or return modified data. */
155
+ onBeforeFormCreated?: (data: FormInput, ctx: FormBuilderHookContext) => Promise<FormInput | void> | FormInput | void;
156
156
  /** Called after a form is created */
157
157
  onAfterFormCreated?: (form: SerializedForm, ctx: FormBuilderHookContext) => Promise<void> | void;
158
- /** Called before getting a form by ID or slug. Return false to deny access. */
159
- onBeforeGetForm?: (idOrSlug: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
160
- /** Called before updating a form. Return false to deny, or modified data. */
161
- onBeforeFormUpdated?: (id: string, data: FormUpdate, ctx: FormBuilderHookContext) => Promise<FormUpdate | false> | FormUpdate | false;
158
+ /** Called before getting a form by ID or slug. Throw an error to deny access. */
159
+ onBeforeGetForm?: (idOrSlug: string, ctx: FormBuilderHookContext) => Promise<void> | void;
160
+ /** Called before updating a form. Throw an error to deny, or return modified data. */
161
+ onBeforeFormUpdated?: (id: string, data: FormUpdate, ctx: FormBuilderHookContext) => Promise<FormUpdate | void> | FormUpdate | void;
162
162
  /** Called after a form is updated */
163
163
  onAfterFormUpdated?: (form: SerializedForm, ctx: FormBuilderHookContext) => Promise<void> | void;
164
- /** Called before deleting a form. Return false to deny. */
165
- onBeforeFormDeleted?: (id: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
164
+ /** Called before deleting a form. Throw an error to deny. */
165
+ onBeforeFormDeleted?: (id: string, ctx: FormBuilderHookContext) => Promise<void> | void;
166
166
  /** Called after a form is deleted */
167
167
  onAfterFormDeleted?: (id: string, ctx: FormBuilderHookContext) => Promise<void> | void;
168
168
  /**
169
169
  * Called before processing a form submission.
170
170
  * Use for: spam protection, rate limiting, data validation/enrichment.
171
171
  *
172
- * @returns false to reject submission (400), or modified data to continue
172
+ * Throw an error to reject submission (400), or return modified data to continue.
173
173
  */
174
- onBeforeSubmission?: (formSlug: string, data: Record<string, unknown>, ctx: SubmissionHookContext) => Promise<Record<string, unknown> | false> | Record<string, unknown> | false;
174
+ onBeforeSubmission?: (formSlug: string, data: Record<string, unknown>, ctx: SubmissionHookContext) => Promise<Record<string, unknown> | void> | Record<string, unknown> | void;
175
175
  /**
176
176
  * Called after a submission is saved.
177
177
  * Use for: sending emails, storing in CRM, triggering workflows.
@@ -179,12 +179,12 @@ interface FormBuilderBackendHooks {
179
179
  onAfterSubmission?: (submission: SerializedFormSubmission, form: SerializedForm, ctx: SubmissionHookContext) => Promise<void> | void;
180
180
  /** Called when a submission fails */
181
181
  onSubmissionError?: (error: Error, formSlug: string, data: Record<string, unknown>, ctx: SubmissionHookContext) => Promise<void> | void;
182
- /** Called before listing submissions. Return false to deny access (403). */
183
- onBeforeListSubmissions?: (formId: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
184
- /** Called before getting a submission. Return false to deny access. */
185
- onBeforeGetSubmission?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
186
- /** Called before deleting a submission. Return false to deny. */
187
- onBeforeSubmissionDeleted?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<boolean> | boolean;
182
+ /** Called before listing submissions. Throw an error to deny access (403). */
183
+ onBeforeListSubmissions?: (formId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
184
+ /** Called before getting a submission. Throw an error to deny access. */
185
+ onBeforeGetSubmission?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
186
+ /** Called before deleting a submission. Throw an error to deny. */
187
+ onBeforeSubmissionDeleted?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
188
188
  /** Called after a submission is deleted */
189
189
  onAfterSubmissionDeleted?: (submissionId: string, ctx: FormBuilderHookContext) => Promise<void> | void;
190
190
  /** Called on any error */