@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
@@ -0,0 +1,46 @@
1
+ import { serializeContentItem } from './getters.mjs';
2
+
3
+ async function createCMSContentItem(adapter, contentTypeSlug, input) {
4
+ const contentType = await adapter.findOne({
5
+ model: "contentType",
6
+ where: [
7
+ {
8
+ field: "slug",
9
+ value: contentTypeSlug,
10
+ operator: "eq"
11
+ }
12
+ ]
13
+ });
14
+ if (!contentType) {
15
+ throw new Error(`Content type "${contentTypeSlug}" not found`);
16
+ }
17
+ const existing = await adapter.findOne({
18
+ model: "contentItem",
19
+ where: [
20
+ {
21
+ field: "contentTypeId",
22
+ value: contentType.id,
23
+ operator: "eq"
24
+ },
25
+ { field: "slug", value: input.slug, operator: "eq" }
26
+ ]
27
+ });
28
+ if (existing) {
29
+ throw new Error(
30
+ `Content item with slug "${input.slug}" already exists in type "${contentTypeSlug}"`
31
+ );
32
+ }
33
+ const item = await adapter.create({
34
+ model: "contentItem",
35
+ data: {
36
+ contentTypeId: contentType.id,
37
+ slug: input.slug,
38
+ data: JSON.stringify(input.data),
39
+ createdAt: /* @__PURE__ */ new Date(),
40
+ updatedAt: /* @__PURE__ */ new Date()
41
+ }
42
+ });
43
+ return serializeContentItem(item);
44
+ }
45
+
46
+ export { createCMSContentItem };
@@ -7,7 +7,9 @@ const db = require('../db.cjs');
7
7
  const schemas = require('../schemas.cjs');
8
8
  const utils = require('../utils.cjs');
9
9
  const getters = require('./getters.cjs');
10
+ const mutations = require('./mutations.cjs');
10
11
  const queryKeyDefs = require('./query-key-defs.cjs');
12
+ const utils$1 = require('../../utils.cjs');
11
13
 
12
14
  async function syncContentTypes(adapter, config) {
13
15
  for (const ct of config.contentTypes) {
@@ -327,7 +329,12 @@ const cmsBackendPlugin = (config) => {
327
329
  await ensureSynced(adapter);
328
330
  return getters.getContentItemById(adapter, id);
329
331
  },
330
- prefetchForRoute: createCMSPrefetchForRoute(adapter)
332
+ prefetchForRoute: createCMSPrefetchForRoute(adapter),
333
+ // Mutations
334
+ createContentItem: async (typeSlug, input) => {
335
+ await ensureSynced(adapter);
336
+ return mutations.createCMSContentItem(adapter, typeSlug, input);
337
+ }
331
338
  }),
332
339
  routes: (adapter) => {
333
340
  const getContentType = async (slug) => {
@@ -483,13 +490,11 @@ const cmsBackendPlugin = (config) => {
483
490
  }
484
491
  const processedData = validation.data;
485
492
  if (config.hooks?.onBeforeCreate) {
486
- const result = await config.hooks.onBeforeCreate(
487
- processedData,
488
- context
493
+ await utils$1.runHookWithShim(
494
+ () => config.hooks.onBeforeCreate(processedData, context),
495
+ ctx.error,
496
+ "Create operation denied"
489
497
  );
490
- if (result === false) {
491
- throw ctx.error(403, { message: "Create operation denied" });
492
- }
493
498
  }
494
499
  const item = await adapter.create({
495
500
  model: "contentItem",
@@ -593,14 +598,11 @@ const cmsBackendPlugin = (config) => {
593
598
  }
594
599
  const processedData = validatedData;
595
600
  if (config.hooks?.onBeforeUpdate && validatedData) {
596
- const result = await config.hooks.onBeforeUpdate(
597
- id,
598
- validatedData,
599
- context
601
+ await utils$1.runHookWithShim(
602
+ () => config.hooks.onBeforeUpdate(id, validatedData, context),
603
+ ctx.error,
604
+ "Update operation denied"
600
605
  );
601
- if (result === false) {
602
- throw ctx.error(403, { message: "Update operation denied" });
603
- }
604
606
  }
605
607
  if (relationIds) {
606
608
  await syncRelations(adapter, id, relationIds);
@@ -651,10 +653,11 @@ const cmsBackendPlugin = (config) => {
651
653
  throw ctx.error(404, { message: "Content item not found" });
652
654
  }
653
655
  if (config.hooks?.onBeforeDelete) {
654
- const canDelete = await config.hooks.onBeforeDelete(id, context);
655
- if (!canDelete) {
656
- throw ctx.error(403, { message: "Delete operation denied" });
657
- }
656
+ await utils$1.runHookWithShim(
657
+ () => config.hooks.onBeforeDelete(id, context),
658
+ ctx.error,
659
+ "Delete operation denied"
660
+ );
658
661
  }
659
662
  await adapter.delete({
660
663
  model: "contentItem",
@@ -5,7 +5,9 @@ import { cmsSchema } from '../db.mjs';
5
5
  import { listContentQuerySchema } from '../schemas.mjs';
6
6
  import { slugify } from '../utils.mjs';
7
7
  import { serializeContentType, getAllContentItems, serializeContentItemWithType, serializeContentItem, getContentItemById, getContentItemBySlug, getAllContentTypes } from './getters.mjs';
8
+ import { createCMSContentItem } from './mutations.mjs';
8
9
  import { CMS_QUERY_KEYS } from './query-key-defs.mjs';
10
+ import { runHookWithShim } from '../../utils.mjs';
9
11
 
10
12
  async function syncContentTypes(adapter, config) {
11
13
  for (const ct of config.contentTypes) {
@@ -325,7 +327,12 @@ const cmsBackendPlugin = (config) => {
325
327
  await ensureSynced(adapter);
326
328
  return getContentItemById(adapter, id);
327
329
  },
328
- prefetchForRoute: createCMSPrefetchForRoute(adapter)
330
+ prefetchForRoute: createCMSPrefetchForRoute(adapter),
331
+ // Mutations
332
+ createContentItem: async (typeSlug, input) => {
333
+ await ensureSynced(adapter);
334
+ return createCMSContentItem(adapter, typeSlug, input);
335
+ }
329
336
  }),
330
337
  routes: (adapter) => {
331
338
  const getContentType = async (slug) => {
@@ -481,13 +488,11 @@ const cmsBackendPlugin = (config) => {
481
488
  }
482
489
  const processedData = validation.data;
483
490
  if (config.hooks?.onBeforeCreate) {
484
- const result = await config.hooks.onBeforeCreate(
485
- processedData,
486
- context
491
+ await runHookWithShim(
492
+ () => config.hooks.onBeforeCreate(processedData, context),
493
+ ctx.error,
494
+ "Create operation denied"
487
495
  );
488
- if (result === false) {
489
- throw ctx.error(403, { message: "Create operation denied" });
490
- }
491
496
  }
492
497
  const item = await adapter.create({
493
498
  model: "contentItem",
@@ -591,14 +596,11 @@ const cmsBackendPlugin = (config) => {
591
596
  }
592
597
  const processedData = validatedData;
593
598
  if (config.hooks?.onBeforeUpdate && validatedData) {
594
- const result = await config.hooks.onBeforeUpdate(
595
- id,
596
- validatedData,
597
- context
599
+ await runHookWithShim(
600
+ () => config.hooks.onBeforeUpdate(id, validatedData, context),
601
+ ctx.error,
602
+ "Update operation denied"
598
603
  );
599
- if (result === false) {
600
- throw ctx.error(403, { message: "Update operation denied" });
601
- }
602
604
  }
603
605
  if (relationIds) {
604
606
  await syncRelations(adapter, id, relationIds);
@@ -649,10 +651,11 @@ const cmsBackendPlugin = (config) => {
649
651
  throw ctx.error(404, { message: "Content item not found" });
650
652
  }
651
653
  if (config.hooks?.onBeforeDelete) {
652
- const canDelete = await config.hooks.onBeforeDelete(id, context);
653
- if (!canDelete) {
654
- throw ctx.error(403, { message: "Delete operation denied" });
655
- }
654
+ await runHookWithShim(
655
+ () => config.hooks.onBeforeDelete(id, context),
656
+ ctx.error,
657
+ "Delete operation denied"
658
+ );
656
659
  }
657
660
  await adapter.delete({
658
661
  model: "contentItem",
@@ -34,10 +34,10 @@ function createDashboardLoader(config) {
34
34
  };
35
35
  try {
36
36
  if (hooks?.beforeLoadDashboard) {
37
- const canLoad = await hooks.beforeLoadDashboard(context);
38
- if (!canLoad) {
39
- throw new Error("Load prevented by beforeLoadDashboard hook");
40
- }
37
+ await client.runClientHookWithShim(
38
+ () => hooks.beforeLoadDashboard(context),
39
+ "Load prevented by beforeLoadDashboard hook"
40
+ );
41
41
  }
42
42
  const client$1 = client.createApiClient({
43
43
  baseURL: apiBaseURL,
@@ -82,10 +82,10 @@ function createContentListLoader(typeSlug, config) {
82
82
  };
83
83
  try {
84
84
  if (hooks?.beforeLoadContentList) {
85
- const canLoad = await hooks.beforeLoadContentList(typeSlug, context);
86
- if (!canLoad) {
87
- throw new Error("Load prevented by beforeLoadContentList hook");
88
- }
85
+ await client.runClientHookWithShim(
86
+ () => hooks.beforeLoadContentList(typeSlug, context),
87
+ "Load prevented by beforeLoadContentList hook"
88
+ );
89
89
  }
90
90
  const client$1 = client.createApiClient({
91
91
  baseURL: apiBaseURL,
@@ -154,14 +154,10 @@ function createContentEditorLoader(typeSlug, id, config) {
154
154
  };
155
155
  try {
156
156
  if (hooks?.beforeLoadContentEditor) {
157
- const canLoad = await hooks.beforeLoadContentEditor(
158
- typeSlug,
159
- id,
160
- context
157
+ await client.runClientHookWithShim(
158
+ () => hooks.beforeLoadContentEditor(typeSlug, id, context),
159
+ "Load prevented by beforeLoadContentEditor hook"
161
160
  );
162
- if (!canLoad) {
163
- throw new Error("Load prevented by beforeLoadContentEditor hook");
164
- }
165
161
  }
166
162
  const client$1 = client.createApiClient({
167
163
  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 { createCMSQueryKeys } from '../../../../../../plugins/cms/query-keys.mjs';
6
6
 
@@ -32,10 +32,10 @@ function createDashboardLoader(config) {
32
32
  };
33
33
  try {
34
34
  if (hooks?.beforeLoadDashboard) {
35
- const canLoad = await hooks.beforeLoadDashboard(context);
36
- if (!canLoad) {
37
- throw new Error("Load prevented by beforeLoadDashboard hook");
38
- }
35
+ await runClientHookWithShim(
36
+ () => hooks.beforeLoadDashboard(context),
37
+ "Load prevented by beforeLoadDashboard hook"
38
+ );
39
39
  }
40
40
  const client = createApiClient({
41
41
  baseURL: apiBaseURL,
@@ -80,10 +80,10 @@ function createContentListLoader(typeSlug, config) {
80
80
  };
81
81
  try {
82
82
  if (hooks?.beforeLoadContentList) {
83
- const canLoad = await hooks.beforeLoadContentList(typeSlug, context);
84
- if (!canLoad) {
85
- throw new Error("Load prevented by beforeLoadContentList hook");
86
- }
83
+ await runClientHookWithShim(
84
+ () => hooks.beforeLoadContentList(typeSlug, context),
85
+ "Load prevented by beforeLoadContentList hook"
86
+ );
87
87
  }
88
88
  const client = createApiClient({
89
89
  baseURL: apiBaseURL,
@@ -152,14 +152,10 @@ function createContentEditorLoader(typeSlug, id, config) {
152
152
  };
153
153
  try {
154
154
  if (hooks?.beforeLoadContentEditor) {
155
- const canLoad = await hooks.beforeLoadContentEditor(
156
- typeSlug,
157
- id,
158
- context
155
+ await runClientHookWithShim(
156
+ () => hooks.beforeLoadContentEditor(typeSlug, id, context),
157
+ "Load prevented by beforeLoadContentEditor hook"
159
158
  );
160
- if (!canLoad) {
161
- throw new Error("Load prevented by beforeLoadContentEditor hook");
162
- }
163
159
  }
164
160
  const client = createApiClient({
165
161
  baseURL: apiBaseURL,
@@ -8,6 +8,7 @@ const schemas = require('../schemas.cjs');
8
8
  const utils = require('../utils.cjs');
9
9
  const getters = require('./getters.cjs');
10
10
  const queryKeyDefs = require('./query-key-defs.cjs');
11
+ const utils$1 = require('../../utils.cjs');
11
12
 
12
13
  function createFormBuilderPrefetchForRoute(adapter) {
13
14
  return async function prefetchForRoute(key, qc, params) {
@@ -98,10 +99,11 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
98
99
  const { status, limit, offset } = ctx.query;
99
100
  const context = createContext(ctx.headers);
100
101
  if (config.hooks?.onBeforeListForms) {
101
- const canList = await config.hooks.onBeforeListForms(context);
102
- if (!canList) {
103
- throw ctx.error(403, { message: "Access denied" });
104
- }
102
+ await utils$1.runHookWithShim(
103
+ () => config.hooks.onBeforeListForms(context),
104
+ ctx.error,
105
+ "Access denied"
106
+ );
105
107
  }
106
108
  return getters.getAllForms(adapter, { status, limit, offset });
107
109
  }
@@ -116,10 +118,11 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
116
118
  const { slug } = ctx.params;
117
119
  const context = createContext(ctx.headers);
118
120
  if (config.hooks?.onBeforeGetForm) {
119
- const canGet = await config.hooks.onBeforeGetForm(slug, context);
120
- if (!canGet) {
121
- throw ctx.error(403, { message: "Access denied" });
122
- }
121
+ await utils$1.runHookWithShim(
122
+ () => config.hooks.onBeforeGetForm(slug, context),
123
+ ctx.error,
124
+ "Access denied"
125
+ );
123
126
  }
124
127
  const form = await getters.getFormBySlug(adapter, slug);
125
128
  if (!form) {
@@ -138,10 +141,11 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
138
141
  const { id } = ctx.params;
139
142
  const context = createContext(ctx.headers);
140
143
  if (config.hooks?.onBeforeGetForm) {
141
- const canGet = await config.hooks.onBeforeGetForm(id, context);
142
- if (!canGet) {
143
- throw ctx.error(403, { message: "Access denied" });
144
- }
144
+ await utils$1.runHookWithShim(
145
+ () => config.hooks.onBeforeGetForm(id, context),
146
+ ctx.error,
147
+ "Access denied"
148
+ );
145
149
  }
146
150
  const form = await adapter.findOne({
147
151
  model: "form",
@@ -192,15 +196,13 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
192
196
  status: body.status
193
197
  };
194
198
  if (config.hooks?.onBeforeFormCreated) {
195
- const result = await config.hooks.onBeforeFormCreated(
196
- formInput,
197
- context
199
+ const hookResult = await utils$1.runHookWithShim(
200
+ () => config.hooks.onBeforeFormCreated(formInput, context),
201
+ ctx.error,
202
+ "Create operation denied"
198
203
  );
199
- if (result === false) {
200
- throw ctx.error(403, { message: "Create operation denied" });
201
- }
202
- if (result && typeof result === "object") {
203
- formInput = result;
204
+ if (hookResult && typeof hookResult === "object") {
205
+ formInput = hookResult;
204
206
  }
205
207
  }
206
208
  const form = await adapter.create({
@@ -282,16 +284,13 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
282
284
  status: body.status
283
285
  };
284
286
  if (config.hooks?.onBeforeFormUpdated) {
285
- const result = await config.hooks.onBeforeFormUpdated(
286
- id,
287
- updateInput,
288
- context
287
+ const hookResult = await utils$1.runHookWithShim(
288
+ () => config.hooks.onBeforeFormUpdated(id, updateInput, context),
289
+ ctx.error,
290
+ "Update operation denied"
289
291
  );
290
- if (result === false) {
291
- throw ctx.error(403, { message: "Update operation denied" });
292
- }
293
- if (result && typeof result === "object") {
294
- updateInput = result;
292
+ if (hookResult && typeof hookResult === "object") {
293
+ updateInput = hookResult;
295
294
  }
296
295
  }
297
296
  const updateData = {
@@ -343,13 +342,11 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
343
342
  throw ctx.error(404, { message: "Form not found" });
344
343
  }
345
344
  if (config.hooks?.onBeforeFormDeleted) {
346
- const canDelete = await config.hooks.onBeforeFormDeleted(
347
- id,
348
- context
345
+ await utils$1.runHookWithShim(
346
+ () => config.hooks.onBeforeFormDeleted(id, context),
347
+ ctx.error,
348
+ "Delete operation denied"
349
349
  );
350
- if (!canDelete) {
351
- throw ctx.error(403, { message: "Delete operation denied" });
352
- }
353
350
  }
354
351
  await adapter.delete({
355
352
  model: "formSubmission",
@@ -414,28 +411,33 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
414
411
  }
415
412
  let finalData = data;
416
413
  if (config.hooks?.onBeforeSubmission) {
414
+ let hookResult;
415
+ let originalError;
417
416
  try {
418
- const result = await config.hooks.onBeforeSubmission(
417
+ hookResult = await config.hooks.onBeforeSubmission(
419
418
  slug,
420
419
  data,
421
420
  submissionContext
422
421
  );
423
- if (result === false) {
424
- throw ctx.error(400, { message: "Submission rejected" });
425
- }
426
- if (result && typeof result === "object") {
427
- finalData = result;
422
+ if (hookResult === false) {
423
+ originalError = new Error("Submission rejected");
428
424
  }
429
- } catch (error) {
425
+ } catch (e) {
426
+ originalError = e instanceof Error ? e : new Error("Submission rejected");
427
+ }
428
+ if (originalError) {
430
429
  if (config.hooks?.onSubmissionError) {
431
430
  await config.hooks.onSubmissionError(
432
- error,
431
+ originalError,
433
432
  slug,
434
433
  data,
435
434
  submissionContext
436
435
  );
437
436
  }
438
- throw error;
437
+ throw ctx.error(400, { message: originalError.message });
438
+ }
439
+ if (hookResult && typeof hookResult === "object") {
440
+ finalData = hookResult;
439
441
  }
440
442
  }
441
443
  const submission = await adapter.create({
@@ -484,13 +486,11 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
484
486
  throw ctx.error(404, { message: "Form not found" });
485
487
  }
486
488
  if (config.hooks?.onBeforeListSubmissions) {
487
- const canList = await config.hooks.onBeforeListSubmissions(
488
- formId,
489
- context
489
+ await utils$1.runHookWithShim(
490
+ () => config.hooks.onBeforeListSubmissions(formId, context),
491
+ ctx.error,
492
+ "Access denied"
490
493
  );
491
- if (!canList) {
492
- throw ctx.error(403, { message: "Access denied" });
493
- }
494
494
  }
495
495
  return getters.getFormSubmissions(adapter, formId, { limit, offset });
496
496
  }
@@ -505,13 +505,11 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
505
505
  const { formId, subId } = ctx.params;
506
506
  const context = createContext(ctx.headers);
507
507
  if (config.hooks?.onBeforeGetSubmission) {
508
- const canGet = await config.hooks.onBeforeGetSubmission(
509
- subId,
510
- context
508
+ await utils$1.runHookWithShim(
509
+ () => config.hooks.onBeforeGetSubmission(subId, context),
510
+ ctx.error,
511
+ "Access denied"
511
512
  );
512
- if (!canGet) {
513
- throw ctx.error(403, { message: "Access denied" });
514
- }
515
513
  }
516
514
  const submission = await adapter.findOne({
517
515
  model: "formSubmission",
@@ -541,13 +539,11 @@ const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
541
539
  throw ctx.error(404, { message: "Submission not found" });
542
540
  }
543
541
  if (config.hooks?.onBeforeSubmissionDeleted) {
544
- const canDelete = await config.hooks.onBeforeSubmissionDeleted(
545
- subId,
546
- context
542
+ await utils$1.runHookWithShim(
543
+ () => config.hooks.onBeforeSubmissionDeleted(subId, context),
544
+ ctx.error,
545
+ "Delete operation denied"
547
546
  );
548
- if (!canDelete) {
549
- throw ctx.error(403, { message: "Delete operation denied" });
550
- }
551
547
  }
552
548
  await adapter.delete({
553
549
  model: "formSubmission",