@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
@@ -6,6 +6,7 @@ import { listFormsQuerySchema, createFormSchema, updateFormSchema, listSubmissio
6
6
  import { extractUserAgent, extractIpAddress, slugify } from '../utils.mjs';
7
7
  import { getFormSubmissions, getFormBySlug, getFormById, getAllForms, serializeForm, serializeFormSubmission, serializeFormSubmissionWithData } from './getters.mjs';
8
8
  import { FORM_QUERY_KEYS } from './query-key-defs.mjs';
9
+ import { runHookWithShim } from '../../utils.mjs';
9
10
 
10
11
  function createFormBuilderPrefetchForRoute(adapter) {
11
12
  return async function prefetchForRoute(key, qc, params) {
@@ -96,10 +97,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
96
97
  const { status, limit, offset } = ctx.query;
97
98
  const context = createContext(ctx.headers);
98
99
  if (config.hooks?.onBeforeListForms) {
99
- const canList = await config.hooks.onBeforeListForms(context);
100
- if (!canList) {
101
- throw ctx.error(403, { message: "Access denied" });
102
- }
100
+ await runHookWithShim(
101
+ () => config.hooks.onBeforeListForms(context),
102
+ ctx.error,
103
+ "Access denied"
104
+ );
103
105
  }
104
106
  return getAllForms(adapter, { status, limit, offset });
105
107
  }
@@ -114,10 +116,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
114
116
  const { slug } = ctx.params;
115
117
  const context = createContext(ctx.headers);
116
118
  if (config.hooks?.onBeforeGetForm) {
117
- const canGet = await config.hooks.onBeforeGetForm(slug, context);
118
- if (!canGet) {
119
- throw ctx.error(403, { message: "Access denied" });
120
- }
119
+ await runHookWithShim(
120
+ () => config.hooks.onBeforeGetForm(slug, context),
121
+ ctx.error,
122
+ "Access denied"
123
+ );
121
124
  }
122
125
  const form = await getFormBySlug(adapter, slug);
123
126
  if (!form) {
@@ -136,10 +139,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
136
139
  const { id } = ctx.params;
137
140
  const context = createContext(ctx.headers);
138
141
  if (config.hooks?.onBeforeGetForm) {
139
- const canGet = await config.hooks.onBeforeGetForm(id, context);
140
- if (!canGet) {
141
- throw ctx.error(403, { message: "Access denied" });
142
- }
142
+ await runHookWithShim(
143
+ () => config.hooks.onBeforeGetForm(id, context),
144
+ ctx.error,
145
+ "Access denied"
146
+ );
143
147
  }
144
148
  const form = await adapter.findOne({
145
149
  model: "form",
@@ -190,15 +194,13 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
190
194
  status: body.status
191
195
  };
192
196
  if (config.hooks?.onBeforeFormCreated) {
193
- const result = await config.hooks.onBeforeFormCreated(
194
- formInput,
195
- context
197
+ const hookResult = await runHookWithShim(
198
+ () => config.hooks.onBeforeFormCreated(formInput, context),
199
+ ctx.error,
200
+ "Create operation denied"
196
201
  );
197
- if (result === false) {
198
- throw ctx.error(403, { message: "Create operation denied" });
199
- }
200
- if (result && typeof result === "object") {
201
- formInput = result;
202
+ if (hookResult && typeof hookResult === "object") {
203
+ formInput = hookResult;
202
204
  }
203
205
  }
204
206
  const form = await adapter.create({
@@ -280,16 +282,13 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
280
282
  status: body.status
281
283
  };
282
284
  if (config.hooks?.onBeforeFormUpdated) {
283
- const result = await config.hooks.onBeforeFormUpdated(
284
- id,
285
- updateInput,
286
- context
285
+ const hookResult = await runHookWithShim(
286
+ () => config.hooks.onBeforeFormUpdated(id, updateInput, context),
287
+ ctx.error,
288
+ "Update operation denied"
287
289
  );
288
- if (result === false) {
289
- throw ctx.error(403, { message: "Update operation denied" });
290
- }
291
- if (result && typeof result === "object") {
292
- updateInput = result;
290
+ if (hookResult && typeof hookResult === "object") {
291
+ updateInput = hookResult;
293
292
  }
294
293
  }
295
294
  const updateData = {
@@ -341,13 +340,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
341
340
  throw ctx.error(404, { message: "Form not found" });
342
341
  }
343
342
  if (config.hooks?.onBeforeFormDeleted) {
344
- const canDelete = await config.hooks.onBeforeFormDeleted(
345
- id,
346
- context
343
+ await runHookWithShim(
344
+ () => config.hooks.onBeforeFormDeleted(id, context),
345
+ ctx.error,
346
+ "Delete operation denied"
347
347
  );
348
- if (!canDelete) {
349
- throw ctx.error(403, { message: "Delete operation denied" });
350
- }
351
348
  }
352
349
  await adapter.delete({
353
350
  model: "formSubmission",
@@ -412,28 +409,33 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
412
409
  }
413
410
  let finalData = data;
414
411
  if (config.hooks?.onBeforeSubmission) {
412
+ let hookResult;
413
+ let originalError;
415
414
  try {
416
- const result = await config.hooks.onBeforeSubmission(
415
+ hookResult = await config.hooks.onBeforeSubmission(
417
416
  slug,
418
417
  data,
419
418
  submissionContext
420
419
  );
421
- if (result === false) {
422
- throw ctx.error(400, { message: "Submission rejected" });
423
- }
424
- if (result && typeof result === "object") {
425
- finalData = result;
420
+ if (hookResult === false) {
421
+ originalError = new Error("Submission rejected");
426
422
  }
427
- } catch (error) {
423
+ } catch (e) {
424
+ originalError = e instanceof Error ? e : new Error("Submission rejected");
425
+ }
426
+ if (originalError) {
428
427
  if (config.hooks?.onSubmissionError) {
429
428
  await config.hooks.onSubmissionError(
430
- error,
429
+ originalError,
431
430
  slug,
432
431
  data,
433
432
  submissionContext
434
433
  );
435
434
  }
436
- throw error;
435
+ throw ctx.error(400, { message: originalError.message });
436
+ }
437
+ if (hookResult && typeof hookResult === "object") {
438
+ finalData = hookResult;
437
439
  }
438
440
  }
439
441
  const submission = await adapter.create({
@@ -482,13 +484,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
482
484
  throw ctx.error(404, { message: "Form not found" });
483
485
  }
484
486
  if (config.hooks?.onBeforeListSubmissions) {
485
- const canList = await config.hooks.onBeforeListSubmissions(
486
- formId,
487
- context
487
+ await runHookWithShim(
488
+ () => config.hooks.onBeforeListSubmissions(formId, context),
489
+ ctx.error,
490
+ "Access denied"
488
491
  );
489
- if (!canList) {
490
- throw ctx.error(403, { message: "Access denied" });
491
- }
492
492
  }
493
493
  return getFormSubmissions(adapter, formId, { limit, offset });
494
494
  }
@@ -503,13 +503,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
503
503
  const { formId, subId } = ctx.params;
504
504
  const context = createContext(ctx.headers);
505
505
  if (config.hooks?.onBeforeGetSubmission) {
506
- const canGet = await config.hooks.onBeforeGetSubmission(
507
- subId,
508
- context
506
+ await runHookWithShim(
507
+ () => config.hooks.onBeforeGetSubmission(subId, context),
508
+ ctx.error,
509
+ "Access denied"
509
510
  );
510
- if (!canGet) {
511
- throw ctx.error(403, { message: "Access denied" });
512
- }
513
511
  }
514
512
  const submission = await adapter.findOne({
515
513
  model: "formSubmission",
@@ -539,13 +537,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
539
537
  throw ctx.error(404, { message: "Submission not found" });
540
538
  }
541
539
  if (config.hooks?.onBeforeSubmissionDeleted) {
542
- const canDelete = await config.hooks.onBeforeSubmissionDeleted(
543
- subId,
544
- context
540
+ await runHookWithShim(
541
+ () => config.hooks.onBeforeSubmissionDeleted(subId, context),
542
+ ctx.error,
543
+ "Delete operation denied"
545
544
  );
546
- if (!canDelete) {
547
- throw ctx.error(403, { message: "Delete operation denied" });
548
- }
549
545
  }
550
546
  await adapter.delete({
551
547
  model: "formSubmission",
@@ -34,10 +34,10 @@ function createFormListLoader(config) {
34
34
  };
35
35
  try {
36
36
  if (hooks?.beforeLoadFormList) {
37
- const canLoad = await hooks.beforeLoadFormList(context);
38
- if (!canLoad) {
39
- throw new Error("Load prevented by beforeLoadFormList hook");
40
- }
37
+ await client.runClientHookWithShim(
38
+ () => hooks.beforeLoadFormList(context),
39
+ "Load prevented by beforeLoadFormList hook"
40
+ );
41
41
  }
42
42
  const client$1 = client.createApiClient({
43
43
  baseURL: apiBaseURL,
@@ -96,10 +96,10 @@ function createFormBuilderLoader(id, config) {
96
96
  };
97
97
  try {
98
98
  if (hooks?.beforeLoadFormBuilder) {
99
- const canLoad = await hooks.beforeLoadFormBuilder(id, context);
100
- if (!canLoad) {
101
- throw new Error("Load prevented by beforeLoadFormBuilder hook");
102
- }
99
+ await client.runClientHookWithShim(
100
+ () => hooks.beforeLoadFormBuilder(id, context),
101
+ "Load prevented by beforeLoadFormBuilder hook"
102
+ );
103
103
  }
104
104
  const client$1 = client.createApiClient({
105
105
  baseURL: apiBaseURL,
@@ -148,10 +148,10 @@ function createSubmissionsLoader(formId, config) {
148
148
  };
149
149
  try {
150
150
  if (hooks?.beforeLoadSubmissions) {
151
- const canLoad = await hooks.beforeLoadSubmissions(formId, context);
152
- if (!canLoad) {
153
- throw new Error("Load prevented by beforeLoadSubmissions hook");
154
- }
151
+ await client.runClientHookWithShim(
152
+ () => hooks.beforeLoadSubmissions(formId, context),
153
+ "Load prevented by beforeLoadSubmissions hook"
154
+ );
155
155
  }
156
156
  const client$1 = client.createApiClient({
157
157
  baseURL: apiBaseURL,
@@ -1,6 +1,6 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { lazy } from 'react';
3
- import { defineClientPlugin, createApiClient, isConnectionError } from '@btst/stack/plugins/client';
3
+ import { defineClientPlugin, createApiClient, runClientHookWithShim, isConnectionError } from '@btst/stack/plugins/client';
4
4
  import { createRoute } from '@btst/yar';
5
5
  import { createFormBuilderQueryKeys } from '../../../../../../plugins/form-builder/query-keys.mjs';
6
6
 
@@ -32,10 +32,10 @@ function createFormListLoader(config) {
32
32
  };
33
33
  try {
34
34
  if (hooks?.beforeLoadFormList) {
35
- const canLoad = await hooks.beforeLoadFormList(context);
36
- if (!canLoad) {
37
- throw new Error("Load prevented by beforeLoadFormList hook");
38
- }
35
+ await runClientHookWithShim(
36
+ () => hooks.beforeLoadFormList(context),
37
+ "Load prevented by beforeLoadFormList hook"
38
+ );
39
39
  }
40
40
  const client = createApiClient({
41
41
  baseURL: apiBaseURL,
@@ -94,10 +94,10 @@ function createFormBuilderLoader(id, config) {
94
94
  };
95
95
  try {
96
96
  if (hooks?.beforeLoadFormBuilder) {
97
- const canLoad = await hooks.beforeLoadFormBuilder(id, context);
98
- if (!canLoad) {
99
- throw new Error("Load prevented by beforeLoadFormBuilder hook");
100
- }
97
+ await runClientHookWithShim(
98
+ () => hooks.beforeLoadFormBuilder(id, context),
99
+ "Load prevented by beforeLoadFormBuilder hook"
100
+ );
101
101
  }
102
102
  const client = createApiClient({
103
103
  baseURL: apiBaseURL,
@@ -146,10 +146,10 @@ function createSubmissionsLoader(formId, config) {
146
146
  };
147
147
  try {
148
148
  if (hooks?.beforeLoadSubmissions) {
149
- const canLoad = await hooks.beforeLoadSubmissions(formId, context);
150
- if (!canLoad) {
151
- throw new Error("Load prevented by beforeLoadSubmissions hook");
152
- }
149
+ await runClientHookWithShim(
150
+ () => hooks.beforeLoadSubmissions(formId, context),
151
+ "Load prevented by beforeLoadSubmissions hook"
152
+ );
153
153
  }
154
154
  const client = createApiClient({
155
155
  baseURL: apiBaseURL,
@@ -0,0 +1,91 @@
1
+ 'use strict';
2
+
3
+ async function createKanbanTask(adapter, input) {
4
+ const existingTasks = await adapter.findMany({
5
+ model: "kanbanTask",
6
+ where: [
7
+ {
8
+ field: "columnId",
9
+ value: input.columnId,
10
+ operator: "eq"
11
+ }
12
+ ]
13
+ });
14
+ const nextOrder = existingTasks.length > 0 ? Math.max(...existingTasks.map((t) => t.order)) + 1 : 0;
15
+ return adapter.create({
16
+ model: "kanbanTask",
17
+ data: {
18
+ title: input.title,
19
+ columnId: input.columnId,
20
+ description: input.description,
21
+ priority: input.priority ?? "MEDIUM",
22
+ order: nextOrder,
23
+ assigneeId: input.assigneeId,
24
+ isArchived: false,
25
+ createdAt: /* @__PURE__ */ new Date(),
26
+ updatedAt: /* @__PURE__ */ new Date()
27
+ }
28
+ });
29
+ }
30
+ const _pendingBoardCreations = /* @__PURE__ */ new Map();
31
+ async function findOrCreateKanbanBoard(adapter, slug, name, columnTitles) {
32
+ const existing = await adapter.findOne({
33
+ model: "kanbanBoard",
34
+ where: [{ field: "slug", value: slug, operator: "eq" }]
35
+ });
36
+ if (existing) return existing;
37
+ const inflight = _pendingBoardCreations.get(slug);
38
+ if (inflight) return inflight;
39
+ const creation = (async () => {
40
+ try {
41
+ const board = await adapter.create({
42
+ model: "kanbanBoard",
43
+ data: {
44
+ name,
45
+ slug,
46
+ createdAt: /* @__PURE__ */ new Date(),
47
+ updatedAt: /* @__PURE__ */ new Date()
48
+ }
49
+ });
50
+ await Promise.all(
51
+ columnTitles.map(
52
+ (title, index) => adapter.create({
53
+ model: "kanbanColumn",
54
+ data: {
55
+ title,
56
+ boardId: board.id,
57
+ order: index,
58
+ createdAt: /* @__PURE__ */ new Date(),
59
+ updatedAt: /* @__PURE__ */ new Date()
60
+ }
61
+ })
62
+ )
63
+ );
64
+ return board;
65
+ } catch (err) {
66
+ const winner = await adapter.findOne({
67
+ model: "kanbanBoard",
68
+ where: [{ field: "slug", value: slug, operator: "eq" }]
69
+ });
70
+ if (winner) return winner;
71
+ throw err;
72
+ }
73
+ })();
74
+ _pendingBoardCreations.set(slug, creation);
75
+ try {
76
+ return await creation;
77
+ } finally {
78
+ _pendingBoardCreations.delete(slug);
79
+ }
80
+ }
81
+ async function getKanbanColumnsByBoardId(adapter, boardId) {
82
+ return adapter.findMany({
83
+ model: "kanbanColumn",
84
+ where: [{ field: "boardId", value: boardId, operator: "eq" }],
85
+ sortBy: { field: "order", direction: "asc" }
86
+ });
87
+ }
88
+
89
+ exports.createKanbanTask = createKanbanTask;
90
+ exports.findOrCreateKanbanBoard = findOrCreateKanbanBoard;
91
+ exports.getKanbanColumnsByBoardId = getKanbanColumnsByBoardId;
@@ -0,0 +1,87 @@
1
+ async function createKanbanTask(adapter, input) {
2
+ const existingTasks = await adapter.findMany({
3
+ model: "kanbanTask",
4
+ where: [
5
+ {
6
+ field: "columnId",
7
+ value: input.columnId,
8
+ operator: "eq"
9
+ }
10
+ ]
11
+ });
12
+ const nextOrder = existingTasks.length > 0 ? Math.max(...existingTasks.map((t) => t.order)) + 1 : 0;
13
+ return adapter.create({
14
+ model: "kanbanTask",
15
+ data: {
16
+ title: input.title,
17
+ columnId: input.columnId,
18
+ description: input.description,
19
+ priority: input.priority ?? "MEDIUM",
20
+ order: nextOrder,
21
+ assigneeId: input.assigneeId,
22
+ isArchived: false,
23
+ createdAt: /* @__PURE__ */ new Date(),
24
+ updatedAt: /* @__PURE__ */ new Date()
25
+ }
26
+ });
27
+ }
28
+ const _pendingBoardCreations = /* @__PURE__ */ new Map();
29
+ async function findOrCreateKanbanBoard(adapter, slug, name, columnTitles) {
30
+ const existing = await adapter.findOne({
31
+ model: "kanbanBoard",
32
+ where: [{ field: "slug", value: slug, operator: "eq" }]
33
+ });
34
+ if (existing) return existing;
35
+ const inflight = _pendingBoardCreations.get(slug);
36
+ if (inflight) return inflight;
37
+ const creation = (async () => {
38
+ try {
39
+ const board = await adapter.create({
40
+ model: "kanbanBoard",
41
+ data: {
42
+ name,
43
+ slug,
44
+ createdAt: /* @__PURE__ */ new Date(),
45
+ updatedAt: /* @__PURE__ */ new Date()
46
+ }
47
+ });
48
+ await Promise.all(
49
+ columnTitles.map(
50
+ (title, index) => adapter.create({
51
+ model: "kanbanColumn",
52
+ data: {
53
+ title,
54
+ boardId: board.id,
55
+ order: index,
56
+ createdAt: /* @__PURE__ */ new Date(),
57
+ updatedAt: /* @__PURE__ */ new Date()
58
+ }
59
+ })
60
+ )
61
+ );
62
+ return board;
63
+ } catch (err) {
64
+ const winner = await adapter.findOne({
65
+ model: "kanbanBoard",
66
+ where: [{ field: "slug", value: slug, operator: "eq" }]
67
+ });
68
+ if (winner) return winner;
69
+ throw err;
70
+ }
71
+ })();
72
+ _pendingBoardCreations.set(slug, creation);
73
+ try {
74
+ return await creation;
75
+ } finally {
76
+ _pendingBoardCreations.delete(slug);
77
+ }
78
+ }
79
+ async function getKanbanColumnsByBoardId(adapter, boardId) {
80
+ return adapter.findMany({
81
+ model: "kanbanColumn",
82
+ where: [{ field: "boardId", value: boardId, operator: "eq" }],
83
+ sortBy: { field: "order", direction: "asc" }
84
+ });
85
+ }
86
+
87
+ export { createKanbanTask, findOrCreateKanbanBoard, getKanbanColumnsByBoardId };