@btst/stack 2.4.0 → 2.5.1

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 (225) hide show
  1. package/dist/node_modules/.pnpm/{@tiptap_core@3.15.3_@tiptap_pm@3.15.3 → @tiptap_core@3.20.0_@tiptap_pm@3.15.3}/node_modules/@tiptap/core/dist/index.cjs +68 -8
  2. package/dist/node_modules/.pnpm/{@tiptap_core@3.15.3_@tiptap_pm@3.15.3 → @tiptap_core@3.20.0_@tiptap_pm@3.15.3}/node_modules/@tiptap/core/dist/index.mjs +68 -8
  3. package/dist/node_modules/.pnpm/{@tiptap_extension-blockquote@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-blockquote@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-blockquote/dist/index.cjs +2 -2
  4. package/dist/node_modules/.pnpm/{@tiptap_extension-blockquote@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-blockquote@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-blockquote/dist/index.mjs +2 -2
  5. package/dist/node_modules/.pnpm/{@tiptap_extension-bold@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-bold@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-bold/dist/index.cjs +2 -2
  6. package/dist/node_modules/.pnpm/{@tiptap_extension-bold@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-bold@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-bold/dist/index.mjs +2 -2
  7. package/dist/node_modules/.pnpm/{@tiptap_extension-bubble-menu@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-bubble-menu@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-bubble-menu/dist/index.cjs +1 -1
  8. package/dist/node_modules/.pnpm/{@tiptap_extension-bubble-menu@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-bubble-menu@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-bubble-menu/dist/index.mjs +1 -1
  9. package/dist/node_modules/.pnpm/{@tiptap_extension-code-block-lowlight@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@ti_2245ac34d84b5693aa60775b0f7781e3 → @tiptap_extension-code-block-lowlight@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@ti_360e739196c451ebf408f4af5a9f3f24}/node_modules/@tiptap/extension-code-block-lowlight/dist/index.cjs +2 -2
  10. package/dist/node_modules/.pnpm/{@tiptap_extension-code-block-lowlight@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@ti_2245ac34d84b5693aa60775b0f7781e3 → @tiptap_extension-code-block-lowlight@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@ti_360e739196c451ebf408f4af5a9f3f24}/node_modules/@tiptap/extension-code-block-lowlight/dist/index.mjs +2 -2
  11. package/dist/node_modules/.pnpm/@tiptap_extension-code-block@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3/node_modules/@tiptap/extension-code-block/dist/index.cjs +319 -0
  12. package/dist/node_modules/.pnpm/@tiptap_extension-code-block@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3/node_modules/@tiptap/extension-code-block/dist/index.mjs +315 -0
  13. package/dist/node_modules/.pnpm/{@tiptap_extension-code-block@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-code-block@3.20.0_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-code-block/dist/index.cjs +1 -1
  14. package/dist/node_modules/.pnpm/{@tiptap_extension-code-block@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-code-block@3.20.0_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-code-block/dist/index.mjs +1 -1
  15. package/dist/node_modules/.pnpm/{@tiptap_extension-code@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-code@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-code/dist/index.cjs +1 -1
  16. package/dist/node_modules/.pnpm/{@tiptap_extension-code@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-code@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-code/dist/index.mjs +1 -1
  17. package/dist/node_modules/.pnpm/{@tiptap_extension-document@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-document@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-document/dist/index.cjs +1 -1
  18. package/dist/node_modules/.pnpm/{@tiptap_extension-document@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-document@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-document/dist/index.mjs +1 -1
  19. package/dist/node_modules/.pnpm/{@tiptap_extension-floating-menu@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-floating-menu@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-floating-menu/dist/index.cjs +1 -1
  20. package/dist/node_modules/.pnpm/{@tiptap_extension-floating-menu@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-floating-menu@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-floating-menu/dist/index.mjs +1 -1
  21. package/dist/node_modules/.pnpm/{@tiptap_extension-hard-break@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-hard-break@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-hard-break/dist/index.cjs +1 -1
  22. package/dist/node_modules/.pnpm/{@tiptap_extension-hard-break@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-hard-break@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-hard-break/dist/index.mjs +1 -1
  23. package/dist/node_modules/.pnpm/{@tiptap_extension-heading@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-heading@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-heading/dist/index.cjs +1 -1
  24. package/dist/node_modules/.pnpm/{@tiptap_extension-heading@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-heading@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-heading/dist/index.mjs +1 -1
  25. package/dist/node_modules/.pnpm/{@tiptap_extension-horizontal-rule@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-horizontal-rule@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-horizontal-rule/dist/index.cjs +1 -1
  26. package/dist/node_modules/.pnpm/{@tiptap_extension-horizontal-rule@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-horizontal-rule@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-horizontal-rule/dist/index.mjs +1 -1
  27. package/dist/node_modules/.pnpm/{@tiptap_extension-image@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-image@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-image/dist/index.cjs +1 -1
  28. package/dist/node_modules/.pnpm/{@tiptap_extension-image@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-image@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-image/dist/index.mjs +1 -1
  29. package/dist/node_modules/.pnpm/{@tiptap_extension-italic@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-italic@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-italic/dist/index.cjs +1 -1
  30. package/dist/node_modules/.pnpm/{@tiptap_extension-italic@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-italic@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-italic/dist/index.mjs +1 -1
  31. package/dist/node_modules/.pnpm/{@tiptap_extension-link@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-link@3.20.0_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-link/dist/index.cjs +28 -22
  32. package/dist/node_modules/.pnpm/{@tiptap_extension-link@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-link@3.20.0_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-link/dist/index.mjs +28 -22
  33. package/dist/node_modules/.pnpm/{@tiptap_extension-list@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-list@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-list/dist/index.cjs +1 -1
  34. package/dist/node_modules/.pnpm/{@tiptap_extension-list@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-list@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-list/dist/index.mjs +1 -1
  35. package/dist/node_modules/.pnpm/{@tiptap_extension-paragraph@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-paragraph@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-paragraph/dist/index.cjs +1 -1
  36. package/dist/node_modules/.pnpm/{@tiptap_extension-paragraph@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-paragraph@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-paragraph/dist/index.mjs +1 -1
  37. package/dist/node_modules/.pnpm/{@tiptap_extension-strike@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-strike@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-strike/dist/index.cjs +1 -1
  38. package/dist/node_modules/.pnpm/{@tiptap_extension-strike@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-strike@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-strike/dist/index.mjs +1 -1
  39. package/dist/node_modules/.pnpm/{@tiptap_extension-table@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-table@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-table/dist/index.cjs +1 -1
  40. package/dist/node_modules/.pnpm/{@tiptap_extension-table@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extension-table@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extension-table/dist/index.mjs +1 -1
  41. package/dist/node_modules/.pnpm/{@tiptap_extension-text-style@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-text-style@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-text-style/dist/index.cjs +1 -1
  42. package/dist/node_modules/.pnpm/{@tiptap_extension-text-style@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-text-style@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-text-style/dist/index.mjs +1 -1
  43. package/dist/node_modules/.pnpm/{@tiptap_extension-text@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-text@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-text/dist/index.cjs +1 -1
  44. package/dist/node_modules/.pnpm/{@tiptap_extension-text@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-text@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-text/dist/index.mjs +1 -1
  45. package/dist/node_modules/.pnpm/{@tiptap_extension-typography@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-typography@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-typography/dist/index.cjs +1 -1
  46. package/dist/node_modules/.pnpm/{@tiptap_extension-typography@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-typography@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-typography/dist/index.mjs +1 -1
  47. package/dist/node_modules/.pnpm/{@tiptap_extension-underline@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-underline@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-underline/dist/index.cjs +1 -1
  48. package/dist/node_modules/.pnpm/{@tiptap_extension-underline@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3_ → @tiptap_extension-underline@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3_}/node_modules/@tiptap/extension-underline/dist/index.mjs +1 -1
  49. package/dist/node_modules/.pnpm/{@tiptap_extensions@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extensions@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extensions/dist/index.cjs +1 -1
  50. package/dist/node_modules/.pnpm/{@tiptap_extensions@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_extensions@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/extensions/dist/index.mjs +1 -1
  51. package/dist/node_modules/.pnpm/{@tiptap_markdown@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_markdown@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/markdown/dist/index.cjs +1 -1
  52. package/dist/node_modules/.pnpm/{@tiptap_markdown@3.15.3_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3 → @tiptap_markdown@3.15.3_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tiptap_pm@3.15.3}/node_modules/@tiptap/markdown/dist/index.mjs +1 -1
  53. package/dist/node_modules/.pnpm/{@tiptap_react@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tip_d7a2a9a319317617a8908309649a6dda → @tiptap_react@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tip_b42b5b2d59902d8a01cd4cc3e2d5dc64}/node_modules/@tiptap/react/dist/index.cjs +1 -1
  54. package/dist/node_modules/.pnpm/{@tiptap_react@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tip_d7a2a9a319317617a8908309649a6dda → @tiptap_react@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tip_b42b5b2d59902d8a01cd4cc3e2d5dc64}/node_modules/@tiptap/react/dist/index.mjs +2 -2
  55. package/dist/node_modules/.pnpm/{@tiptap_react@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tip_d7a2a9a319317617a8908309649a6dda → @tiptap_react@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tip_b42b5b2d59902d8a01cd4cc3e2d5dc64}/node_modules/@tiptap/react/dist/menus/index.cjs +2 -2
  56. package/dist/node_modules/.pnpm/{@tiptap_react@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.15.3_@tiptap_pm@3.15.3__@tip_d7a2a9a319317617a8908309649a6dda → @tiptap_react@3.15.3_@floating-ui_dom@1.7.4_@tiptap_core@3.20.0_@tiptap_pm@3.15.3__@tip_b42b5b2d59902d8a01cd4cc3e2d5dc64}/node_modules/@tiptap/react/dist/menus/index.mjs +2 -2
  57. package/dist/node_modules/.pnpm/@tiptap_starter-kit@3.15.3/node_modules/@tiptap/starter-kit/dist/index.cjs +17 -17
  58. package/dist/node_modules/.pnpm/@tiptap_starter-kit@3.15.3/node_modules/@tiptap/starter-kit/dist/index.mjs +17 -17
  59. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.cjs +33 -47
  60. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +33 -47
  61. package/dist/packages/stack/src/plugins/ai-chat/client/plugin.cjs +14 -21
  62. package/dist/packages/stack/src/plugins/ai-chat/client/plugin.mjs +15 -22
  63. package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +28 -45
  64. package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +22 -39
  65. package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +23 -27
  66. package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +24 -28
  67. package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +14 -17
  68. package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +14 -17
  69. package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +11 -15
  70. package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +12 -16
  71. package/dist/packages/stack/src/plugins/form-builder/api/plugin.cjs +58 -62
  72. package/dist/packages/stack/src/plugins/form-builder/api/plugin.mjs +58 -62
  73. package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +12 -12
  74. package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +13 -13
  75. package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +86 -117
  76. package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +83 -114
  77. package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +22 -29
  78. package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +23 -30
  79. package/dist/packages/stack/src/plugins/open-api/api/generator.cjs +2 -1
  80. package/dist/packages/stack/src/plugins/open-api/api/generator.mjs +2 -1
  81. package/dist/packages/stack/src/plugins/ui-builder/client/plugin.cjs +8 -8
  82. package/dist/packages/stack/src/plugins/ui-builder/client/plugin.mjs +9 -9
  83. package/dist/packages/stack/src/plugins/utils.cjs +42 -0
  84. package/dist/packages/stack/src/plugins/utils.mjs +41 -1
  85. package/dist/packages/ui/src/components/minimal-tiptap/components/bubble-menu/link-bubble-menu.cjs +1 -1
  86. package/dist/packages/ui/src/components/minimal-tiptap/components/bubble-menu/link-bubble-menu.mjs +1 -1
  87. package/dist/packages/ui/src/components/minimal-tiptap/extensions/code-block-lowlight/code-block-lowlight.cjs +1 -1
  88. package/dist/packages/ui/src/components/minimal-tiptap/extensions/code-block-lowlight/code-block-lowlight.mjs +1 -1
  89. package/dist/packages/ui/src/components/minimal-tiptap/extensions/color/color.cjs +1 -1
  90. package/dist/packages/ui/src/components/minimal-tiptap/extensions/color/color.mjs +1 -1
  91. package/dist/packages/ui/src/components/minimal-tiptap/extensions/file-handler/index.cjs +1 -1
  92. package/dist/packages/ui/src/components/minimal-tiptap/extensions/file-handler/index.mjs +1 -1
  93. package/dist/packages/ui/src/components/minimal-tiptap/extensions/horizontal-rule/horizontal-rule.cjs +1 -1
  94. package/dist/packages/ui/src/components/minimal-tiptap/extensions/horizontal-rule/horizontal-rule.mjs +1 -1
  95. package/dist/packages/ui/src/components/minimal-tiptap/extensions/image/components/image-view-block.cjs +1 -1
  96. package/dist/packages/ui/src/components/minimal-tiptap/extensions/image/components/image-view-block.mjs +1 -1
  97. package/dist/packages/ui/src/components/minimal-tiptap/extensions/image/image.cjs +2 -2
  98. package/dist/packages/ui/src/components/minimal-tiptap/extensions/image/image.mjs +2 -2
  99. package/dist/packages/ui/src/components/minimal-tiptap/extensions/markdown-paste/markdown-paste.cjs +1 -1
  100. package/dist/packages/ui/src/components/minimal-tiptap/extensions/markdown-paste/markdown-paste.mjs +1 -1
  101. package/dist/packages/ui/src/components/minimal-tiptap/extensions/reset-marks-on-enter/reset-marks-on-enter.cjs +1 -1
  102. package/dist/packages/ui/src/components/minimal-tiptap/extensions/reset-marks-on-enter/reset-marks-on-enter.mjs +1 -1
  103. package/dist/packages/ui/src/components/minimal-tiptap/extensions/unset-all-marks/unset-all-marks.cjs +1 -1
  104. package/dist/packages/ui/src/components/minimal-tiptap/extensions/unset-all-marks/unset-all-marks.mjs +1 -1
  105. package/dist/packages/ui/src/components/minimal-tiptap/hooks/use-minimal-tiptap.cjs +7 -7
  106. package/dist/packages/ui/src/components/minimal-tiptap/hooks/use-minimal-tiptap.mjs +7 -7
  107. package/dist/packages/ui/src/components/minimal-tiptap/hooks/use-tiptap-editor.cjs +1 -1
  108. package/dist/packages/ui/src/components/minimal-tiptap/hooks/use-tiptap-editor.mjs +1 -1
  109. package/dist/packages/ui/src/components/minimal-tiptap/minimal-tiptap.cjs +1 -1
  110. package/dist/packages/ui/src/components/minimal-tiptap/minimal-tiptap.mjs +1 -1
  111. package/dist/plugins/ai-chat/api/index.d.cts +1 -1
  112. package/dist/plugins/ai-chat/api/index.d.mts +1 -1
  113. package/dist/plugins/ai-chat/api/index.d.ts +1 -1
  114. package/dist/plugins/ai-chat/client/hooks/index.d.cts +1 -1
  115. package/dist/plugins/ai-chat/client/hooks/index.d.mts +1 -1
  116. package/dist/plugins/ai-chat/client/hooks/index.d.ts +1 -1
  117. package/dist/plugins/ai-chat/client/index.d.cts +8 -8
  118. package/dist/plugins/ai-chat/client/index.d.mts +8 -8
  119. package/dist/plugins/ai-chat/client/index.d.ts +8 -8
  120. package/dist/plugins/ai-chat/query-keys.d.cts +1 -1
  121. package/dist/plugins/ai-chat/query-keys.d.mts +1 -1
  122. package/dist/plugins/ai-chat/query-keys.d.ts +1 -1
  123. package/dist/plugins/blog/api/index.d.cts +1 -1
  124. package/dist/plugins/blog/api/index.d.mts +1 -1
  125. package/dist/plugins/blog/api/index.d.ts +1 -1
  126. package/dist/plugins/blog/client/index.d.cts +12 -12
  127. package/dist/plugins/blog/client/index.d.mts +12 -12
  128. package/dist/plugins/blog/client/index.d.ts +12 -12
  129. package/dist/plugins/blog/query-keys.d.cts +1 -1
  130. package/dist/plugins/blog/query-keys.d.mts +1 -1
  131. package/dist/plugins/blog/query-keys.d.ts +1 -1
  132. package/dist/plugins/client/index.cjs +1 -0
  133. package/dist/plugins/client/index.d.cts +8 -1
  134. package/dist/plugins/client/index.d.mts +8 -1
  135. package/dist/plugins/client/index.d.ts +8 -1
  136. package/dist/plugins/client/index.mjs +1 -1
  137. package/dist/plugins/cms/api/index.d.cts +2 -2
  138. package/dist/plugins/cms/api/index.d.mts +2 -2
  139. package/dist/plugins/cms/api/index.d.ts +2 -2
  140. package/dist/plugins/cms/client/hooks/index.d.cts +1 -1
  141. package/dist/plugins/cms/client/hooks/index.d.mts +1 -1
  142. package/dist/plugins/cms/client/hooks/index.d.ts +1 -1
  143. package/dist/plugins/cms/client/index.d.cts +6 -6
  144. package/dist/plugins/cms/client/index.d.mts +6 -6
  145. package/dist/plugins/cms/client/index.d.ts +6 -6
  146. package/dist/plugins/cms/query-keys.d.cts +2 -2
  147. package/dist/plugins/cms/query-keys.d.mts +2 -2
  148. package/dist/plugins/cms/query-keys.d.ts +2 -2
  149. package/dist/plugins/form-builder/api/index.d.cts +2 -2
  150. package/dist/plugins/form-builder/api/index.d.mts +2 -2
  151. package/dist/plugins/form-builder/api/index.d.ts +2 -2
  152. package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
  153. package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
  154. package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
  155. package/dist/plugins/form-builder/client/hooks/index.d.cts +1 -1
  156. package/dist/plugins/form-builder/client/hooks/index.d.mts +1 -1
  157. package/dist/plugins/form-builder/client/hooks/index.d.ts +1 -1
  158. package/dist/plugins/form-builder/client/index.d.cts +6 -6
  159. package/dist/plugins/form-builder/client/index.d.mts +6 -6
  160. package/dist/plugins/form-builder/client/index.d.ts +6 -6
  161. package/dist/plugins/form-builder/query-keys.d.cts +2 -2
  162. package/dist/plugins/form-builder/query-keys.d.mts +2 -2
  163. package/dist/plugins/form-builder/query-keys.d.ts +2 -2
  164. package/dist/plugins/kanban/api/index.d.cts +1 -1
  165. package/dist/plugins/kanban/api/index.d.mts +1 -1
  166. package/dist/plugins/kanban/api/index.d.ts +1 -1
  167. package/dist/plugins/kanban/client/index.d.cts +12 -12
  168. package/dist/plugins/kanban/client/index.d.mts +12 -12
  169. package/dist/plugins/kanban/client/index.d.ts +12 -12
  170. package/dist/plugins/kanban/query-keys.d.cts +1 -1
  171. package/dist/plugins/kanban/query-keys.d.mts +1 -1
  172. package/dist/plugins/kanban/query-keys.d.ts +1 -1
  173. package/dist/plugins/ui-builder/client/hooks/index.d.cts +1 -1
  174. package/dist/plugins/ui-builder/client/hooks/index.d.mts +1 -1
  175. package/dist/plugins/ui-builder/client/hooks/index.d.ts +1 -1
  176. package/dist/plugins/ui-builder/client/index.d.cts +3 -3
  177. package/dist/plugins/ui-builder/client/index.d.mts +3 -3
  178. package/dist/plugins/ui-builder/client/index.d.ts +3 -3
  179. package/dist/plugins/ui-builder/index.d.cts +2 -2
  180. package/dist/plugins/ui-builder/index.d.mts +2 -2
  181. package/dist/plugins/ui-builder/index.d.ts +2 -2
  182. package/dist/shared/{stack.C-WUPMT6.d.cts → stack.B2xZTSiO.d.cts} +4 -4
  183. package/dist/shared/{stack.CczspVn2.d.mts → stack.B58oHdqm.d.mts} +1 -1
  184. package/dist/shared/{stack.BepFXT3w.d.mts → stack.B8D4r97Z.d.mts} +22 -22
  185. package/dist/shared/{stack.CVDTkMoO.d.mts → stack.B8QD11QU.d.cts} +7 -7
  186. package/dist/shared/{stack.CVDTkMoO.d.cts → stack.B8QD11QU.d.mts} +7 -7
  187. package/dist/shared/{stack.CVDTkMoO.d.ts → stack.B8QD11QU.d.ts} +7 -7
  188. package/dist/shared/{stack.kcdnD4gA.d.cts → stack.BgTmujxW.d.mts} +1 -1
  189. package/dist/shared/{stack.DdI5W6MB.d.mts → stack.BozPgbrZ.d.cts} +19 -19
  190. package/dist/shared/{stack.DdI5W6MB.d.ts → stack.BozPgbrZ.d.mts} +19 -19
  191. package/dist/shared/{stack.DdI5W6MB.d.cts → stack.BozPgbrZ.d.ts} +19 -19
  192. package/dist/shared/{stack.BUkC2EsZ.d.cts → stack.C9Mg2Q46.d.cts} +1 -1
  193. package/dist/shared/{stack.Kq2-QzOC.d.ts → stack.CLQuVdwK.d.ts} +1 -1
  194. package/dist/shared/{stack.B7ONvlD_.d.mts → stack.CSx98K5H.d.cts} +1 -1
  195. package/dist/shared/{stack.BEn34wW6.d.ts → stack.CTDVxbrA.d.ts} +12 -12
  196. package/dist/shared/{stack.C-Ptrz8s.d.ts → stack.Cj_zKww4.d.ts} +4 -4
  197. package/dist/shared/{stack.DWoCZff7.d.cts → stack.D-b5zbPm.d.cts} +12 -12
  198. package/dist/shared/{stack.CL8ts1Mu.d.ts → stack.DXnclTG7.d.ts} +8 -8
  199. package/dist/shared/{stack.heOA9gzA.d.cts → stack.DaZM10cp.d.cts} +8 -8
  200. package/dist/shared/{stack.CgWzG5jH.d.ts → stack.DgKOwl20.d.ts} +22 -22
  201. package/dist/shared/{stack.DTDxgFj8.d.mts → stack.FVWf2JhZ.d.mts} +12 -12
  202. package/dist/shared/{stack.Dk5r4W1F.d.mts → stack.cfCkioTe.d.mts} +8 -8
  203. package/dist/shared/{stack.6fUOjLs9.d.mts → stack.dH7u-TJH.d.mts} +4 -4
  204. package/dist/shared/{stack.DASmUVjX.d.ts → stack.sO33ZDhK.d.ts} +1 -1
  205. package/dist/shared/{stack.D3GB6wKv.d.cts → stack.uWSqCWAb.d.cts} +22 -22
  206. package/package.json +1 -1
  207. package/src/plugins/ai-chat/api/plugin.ts +48 -63
  208. package/src/plugins/ai-chat/client/plugin.tsx +23 -31
  209. package/src/plugins/blog/api/plugin.ts +31 -47
  210. package/src/plugins/blog/client/plugin.tsx +36 -39
  211. package/src/plugins/client/index.ts +5 -1
  212. package/src/plugins/cms/api/plugin.ts +14 -17
  213. package/src/plugins/cms/client/plugin.tsx +18 -21
  214. package/src/plugins/cms/types.ts +7 -7
  215. package/src/plugins/form-builder/api/plugin.ts +64 -64
  216. package/src/plugins/form-builder/client/plugin.tsx +19 -18
  217. package/src/plugins/form-builder/types.ts +19 -24
  218. package/src/plugins/kanban/api/plugin.ts +111 -136
  219. package/src/plugins/kanban/client/plugin.tsx +35 -41
  220. package/src/plugins/open-api/api/generator.ts +3 -1
  221. package/src/plugins/ui-builder/client/plugin.tsx +11 -10
  222. package/src/plugins/ui-builder/types.ts +4 -4
  223. package/src/plugins/utils.ts +92 -1
  224. /package/dist/node_modules/.pnpm/{@tiptap_core@3.15.3_@tiptap_pm@3.15.3 → @tiptap_core@3.20.0_@tiptap_pm@3.15.3}/node_modules/@tiptap/core/dist/jsx-runtime/jsx-runtime.cjs +0 -0
  225. /package/dist/node_modules/.pnpm/{@tiptap_core@3.15.3_@tiptap_pm@3.15.3 → @tiptap_core@3.20.0_@tiptap_pm@3.15.3}/node_modules/@tiptap/core/dist/jsx-runtime/jsx-runtime.mjs +0 -0
@@ -33,6 +33,7 @@ import {
33
33
  import { createCMSContentItem } from "./mutations";
34
34
  import type { QueryClient } from "@tanstack/react-query";
35
35
  import { CMS_QUERY_KEYS } from "./query-key-defs";
36
+ import { runHookWithShim } from "../../utils";
36
37
 
37
38
  /**
38
39
  * Route keys for the CMS plugin — matches the keys returned by
@@ -779,13 +780,11 @@ export const cmsBackendPlugin = (config: CMSBackendConfig) => {
779
780
  // Call before hook - may deny operation
780
781
  const processedData = validation.data as Record<string, unknown>;
781
782
  if (config.hooks?.onBeforeCreate) {
782
- const result = await config.hooks.onBeforeCreate(
783
- processedData,
784
- context,
783
+ await runHookWithShim(
784
+ () => config.hooks!.onBeforeCreate!(processedData, context),
785
+ ctx.error,
786
+ "Create operation denied",
785
787
  );
786
- if (result === false) {
787
- throw ctx.error(403, { message: "Create operation denied" });
788
- }
789
788
  }
790
789
 
791
790
  const item = await adapter.create<ContentItem>({
@@ -922,14 +921,11 @@ export const cmsBackendPlugin = (config: CMSBackendConfig) => {
922
921
  // Call before hook - may deny operation
923
922
  const processedData = validatedData;
924
923
  if (config.hooks?.onBeforeUpdate && validatedData) {
925
- const result = await config.hooks.onBeforeUpdate(
926
- id,
927
- validatedData,
928
- context,
924
+ await runHookWithShim(
925
+ () => config.hooks!.onBeforeUpdate!(id, validatedData, context),
926
+ ctx.error,
927
+ "Update operation denied",
929
928
  );
930
- if (result === false) {
931
- throw ctx.error(403, { message: "Update operation denied" });
932
- }
933
929
  }
934
930
 
935
931
  // Sync relations to junction table if data was updated
@@ -996,10 +992,11 @@ export const cmsBackendPlugin = (config: CMSBackendConfig) => {
996
992
 
997
993
  // Call before hook
998
994
  if (config.hooks?.onBeforeDelete) {
999
- const canDelete = await config.hooks.onBeforeDelete(id, context);
1000
- if (!canDelete) {
1001
- throw ctx.error(403, { message: "Delete operation denied" });
1002
- }
995
+ await runHookWithShim(
996
+ () => config.hooks!.onBeforeDelete!(id, context),
997
+ ctx.error,
998
+ "Delete operation denied",
999
+ );
1003
1000
  }
1004
1001
 
1005
1002
  await adapter.delete({
@@ -3,6 +3,7 @@ import {
3
3
  defineClientPlugin,
4
4
  createApiClient,
5
5
  isConnectionError,
6
+ runClientHookWithShim,
6
7
  } from "@btst/stack/plugins/client";
7
8
  import { createRoute } from "@btst/yar";
8
9
  import type { QueryClient } from "@tanstack/react-query";
@@ -52,24 +53,24 @@ export interface LoaderContext {
52
53
  */
53
54
  export interface CMSClientHooks {
54
55
  /**
55
- * Called before loading the dashboard page. Return false to cancel loading.
56
+ * Called before loading the dashboard page. Throw an error to cancel loading.
56
57
  * @param context - Loader context with path, params, etc.
57
58
  */
58
- beforeLoadDashboard?: (context: LoaderContext) => Promise<boolean> | boolean;
59
+ beforeLoadDashboard?: (context: LoaderContext) => Promise<void> | void;
59
60
  /**
60
61
  * Called after the dashboard is loaded.
61
62
  * @param context - Loader context
62
63
  */
63
64
  afterLoadDashboard?: (context: LoaderContext) => Promise<void> | void;
64
65
  /**
65
- * Called before loading a content list page. Return false to cancel loading.
66
+ * Called before loading a content list page. Throw an error to cancel loading.
66
67
  * @param typeSlug - The content type slug
67
68
  * @param context - Loader context
68
69
  */
69
70
  beforeLoadContentList?: (
70
71
  typeSlug: string,
71
72
  context: LoaderContext,
72
- ) => Promise<boolean> | boolean;
73
+ ) => Promise<void> | void;
73
74
  /**
74
75
  * Called after a content list is loaded.
75
76
  * @param typeSlug - The content type slug
@@ -80,7 +81,7 @@ export interface CMSClientHooks {
80
81
  context: LoaderContext,
81
82
  ) => Promise<void> | void;
82
83
  /**
83
- * Called before loading the content editor page. Return false to cancel loading.
84
+ * Called before loading the content editor page. Throw an error to cancel loading.
84
85
  * @param typeSlug - The content type slug
85
86
  * @param id - The content item ID (undefined for new items)
86
87
  * @param context - Loader context
@@ -89,7 +90,7 @@ export interface CMSClientHooks {
89
90
  typeSlug: string,
90
91
  id: string | undefined,
91
92
  context: LoaderContext,
92
- ) => Promise<boolean> | boolean;
93
+ ) => Promise<void> | void;
93
94
  /**
94
95
  * Called after the content editor is loaded.
95
96
  * @param typeSlug - The content type slug
@@ -149,10 +150,10 @@ function createDashboardLoader(config: CMSClientConfig) {
149
150
  try {
150
151
  // Before hook - authorization check
151
152
  if (hooks?.beforeLoadDashboard) {
152
- const canLoad = await hooks.beforeLoadDashboard(context);
153
- if (!canLoad) {
154
- throw new Error("Load prevented by beforeLoadDashboard hook");
155
- }
153
+ await runClientHookWithShim(
154
+ () => hooks.beforeLoadDashboard!(context),
155
+ "Load prevented by beforeLoadDashboard hook",
156
+ );
156
157
  }
157
158
 
158
159
  const client = createApiClient<CMSApiRouter>({
@@ -217,10 +218,10 @@ function createContentListLoader(typeSlug: string, config: CMSClientConfig) {
217
218
  try {
218
219
  // Before hook - authorization check
219
220
  if (hooks?.beforeLoadContentList) {
220
- const canLoad = await hooks.beforeLoadContentList(typeSlug, context);
221
- if (!canLoad) {
222
- throw new Error("Load prevented by beforeLoadContentList hook");
223
- }
221
+ await runClientHookWithShim(
222
+ () => hooks.beforeLoadContentList!(typeSlug, context),
223
+ "Load prevented by beforeLoadContentList hook",
224
+ );
224
225
  }
225
226
 
226
227
  const client = createApiClient<CMSApiRouter>({
@@ -321,14 +322,10 @@ function createContentEditorLoader(
321
322
  try {
322
323
  // Before hook - authorization check
323
324
  if (hooks?.beforeLoadContentEditor) {
324
- const canLoad = await hooks.beforeLoadContentEditor(
325
- typeSlug,
326
- id,
327
- context,
325
+ await runClientHookWithShim(
326
+ () => hooks.beforeLoadContentEditor!(typeSlug, id, context),
327
+ "Load prevented by beforeLoadContentEditor hook",
328
328
  );
329
- if (!canLoad) {
330
- throw new Error("Load prevented by beforeLoadContentEditor hook");
331
- }
332
329
  }
333
330
 
334
331
  const client = createApiClient<CMSApiRouter>({
@@ -248,16 +248,16 @@ export interface CMSHookContext {
248
248
  /**
249
249
  * Hooks for customizing CMS backend behavior
250
250
  *
251
- * Note: Before hooks can only deny operations by returning `false`.
251
+ * Note: Before hooks deny operations by throwing an error.
252
252
  * They cannot modify the data being saved. This ensures consistency
253
253
  * between the stored content item data and relation junction tables.
254
254
  */
255
255
  export interface CMSBackendHooks {
256
- /** Called before creating a content item. Return false to deny the operation. */
256
+ /** Called before creating a content item. Throw an error to deny the operation. */
257
257
  onBeforeCreate?: (
258
258
  data: Record<string, unknown>,
259
259
  context: CMSHookContext,
260
- ) => Promise<false | void> | false | void;
260
+ ) => Promise<void> | void;
261
261
 
262
262
  /** Called after creating a content item */
263
263
  onAfterCreate?: (
@@ -265,12 +265,12 @@ export interface CMSBackendHooks {
265
265
  context: CMSHookContext,
266
266
  ) => Promise<void> | void;
267
267
 
268
- /** Called before updating a content item. Return false to deny the operation. */
268
+ /** Called before updating a content item. Throw an error to deny the operation. */
269
269
  onBeforeUpdate?: (
270
270
  id: string,
271
271
  data: Record<string, unknown>,
272
272
  context: CMSHookContext,
273
- ) => Promise<false | void> | false | void;
273
+ ) => Promise<void> | void;
274
274
 
275
275
  /** Called after updating a content item */
276
276
  onAfterUpdate?: (
@@ -278,11 +278,11 @@ export interface CMSBackendHooks {
278
278
  context: CMSHookContext,
279
279
  ) => Promise<void> | void;
280
280
 
281
- /** Called before deleting a content item */
281
+ /** Called before deleting a content item. Throw an error to deny the operation. */
282
282
  onBeforeDelete?: (
283
283
  id: string,
284
284
  context: CMSHookContext,
285
- ) => Promise<boolean> | boolean;
285
+ ) => Promise<void> | void;
286
286
 
287
287
  /** Called after deleting a content item */
288
288
  onAfterDelete?: (id: string, context: CMSHookContext) => Promise<void> | void;
@@ -32,6 +32,7 @@ import {
32
32
  } from "./getters";
33
33
  import { FORM_QUERY_KEYS } from "./query-key-defs";
34
34
  import type { QueryClient } from "@tanstack/react-query";
35
+ import { runHookWithShim } from "../../utils";
35
36
 
36
37
  /**
37
38
  * Route keys for the Form Builder plugin — matches the keys returned by
@@ -177,10 +178,11 @@ export const formBuilderBackendPlugin = (
177
178
  const context = createContext(ctx.headers);
178
179
 
179
180
  if (config.hooks?.onBeforeListForms) {
180
- const canList = await config.hooks.onBeforeListForms(context);
181
- if (!canList) {
182
- throw ctx.error(403, { message: "Access denied" });
183
- }
181
+ await runHookWithShim(
182
+ () => config.hooks!.onBeforeListForms!(context),
183
+ ctx.error,
184
+ "Access denied",
185
+ );
184
186
  }
185
187
 
186
188
  return getAllForms(adapter, { status, limit, offset });
@@ -199,10 +201,11 @@ export const formBuilderBackendPlugin = (
199
201
 
200
202
  // Call before hook for access check
201
203
  if (config.hooks?.onBeforeGetForm) {
202
- const canGet = await config.hooks.onBeforeGetForm(slug, context);
203
- if (!canGet) {
204
- throw ctx.error(403, { message: "Access denied" });
205
- }
204
+ await runHookWithShim(
205
+ () => config.hooks!.onBeforeGetForm!(slug, context),
206
+ ctx.error,
207
+ "Access denied",
208
+ );
206
209
  }
207
210
 
208
211
  const form = await getFormBySlugFromDb(adapter, slug);
@@ -227,10 +230,11 @@ export const formBuilderBackendPlugin = (
227
230
 
228
231
  // Call before hook for access check
229
232
  if (config.hooks?.onBeforeGetForm) {
230
- const canGet = await config.hooks.onBeforeGetForm(id, context);
231
- if (!canGet) {
232
- throw ctx.error(403, { message: "Access denied" });
233
- }
233
+ await runHookWithShim(
234
+ () => config.hooks!.onBeforeGetForm!(id, context),
235
+ ctx.error,
236
+ "Access denied",
237
+ );
234
238
  }
235
239
 
236
240
  const form = await adapter.findOne<Form>({
@@ -297,15 +301,13 @@ export const formBuilderBackendPlugin = (
297
301
 
298
302
  // Call before hook - may modify data or deny operation
299
303
  if (config.hooks?.onBeforeFormCreated) {
300
- const result = await config.hooks.onBeforeFormCreated(
301
- formInput,
302
- context,
304
+ const hookResult = await runHookWithShim(
305
+ () => config.hooks!.onBeforeFormCreated!(formInput, context),
306
+ ctx.error,
307
+ "Create operation denied",
303
308
  );
304
- if (result === false) {
305
- throw ctx.error(403, { message: "Create operation denied" });
306
- }
307
- if (result && typeof result === "object") {
308
- formInput = result;
309
+ if (hookResult && typeof hookResult === "object") {
310
+ formInput = hookResult as typeof formInput;
309
311
  }
310
312
  }
311
313
 
@@ -410,16 +412,14 @@ export const formBuilderBackendPlugin = (
410
412
 
411
413
  // Call before hook - may modify data or deny operation
412
414
  if (config.hooks?.onBeforeFormUpdated) {
413
- const result = await config.hooks.onBeforeFormUpdated(
414
- id,
415
- updateInput,
416
- context,
415
+ const hookResult = await runHookWithShim(
416
+ () =>
417
+ config.hooks!.onBeforeFormUpdated!(id, updateInput, context),
418
+ ctx.error,
419
+ "Update operation denied",
417
420
  );
418
- if (result === false) {
419
- throw ctx.error(403, { message: "Update operation denied" });
420
- }
421
- if (result && typeof result === "object") {
422
- updateInput = result;
421
+ if (hookResult && typeof hookResult === "object") {
422
+ updateInput = hookResult as typeof updateInput;
423
423
  }
424
424
  }
425
425
 
@@ -485,13 +485,11 @@ export const formBuilderBackendPlugin = (
485
485
 
486
486
  // Call before hook
487
487
  if (config.hooks?.onBeforeFormDeleted) {
488
- const canDelete = await config.hooks.onBeforeFormDeleted(
489
- id,
490
- context,
488
+ await runHookWithShim(
489
+ () => config.hooks!.onBeforeFormDeleted!(id, context),
490
+ ctx.error,
491
+ "Delete operation denied",
491
492
  );
492
- if (!canDelete) {
493
- throw ctx.error(403, { message: "Delete operation denied" });
494
- }
495
493
  }
496
494
 
497
495
  // Delete associated submissions first (cascade)
@@ -574,32 +572,40 @@ export const formBuilderBackendPlugin = (
574
572
  throw ctx.error(400, { message: "Invalid form data" });
575
573
  }
576
574
 
577
- // Call before submission hook - may modify data or deny
575
+ // Call before submission hook - may modify data or deny.
576
+ // We call the hook directly (not via runHookWithShim) so that
577
+ // onSubmissionError receives the original Error, not a wrapped HTTP error.
578
578
  let finalData = data as Record<string, unknown>;
579
579
  if (config.hooks?.onBeforeSubmission) {
580
+ let hookResult: unknown;
581
+ let originalError: Error | undefined;
580
582
  try {
581
- const result = await config.hooks.onBeforeSubmission(
583
+ hookResult = await config.hooks.onBeforeSubmission(
582
584
  slug,
583
585
  data as Record<string, unknown>,
584
586
  submissionContext,
585
587
  );
586
- if (result === false) {
587
- throw ctx.error(400, { message: "Submission rejected" });
588
- }
589
- if (result && typeof result === "object") {
590
- finalData = result;
588
+ // Backward-compat: explicit false return → denial
589
+ if (hookResult === false) {
590
+ originalError = new Error("Submission rejected");
591
591
  }
592
- } catch (error) {
593
- // Call error hook if submission is rejected
592
+ } catch (e) {
593
+ originalError =
594
+ e instanceof Error ? e : new Error("Submission rejected");
595
+ }
596
+ if (originalError) {
594
597
  if (config.hooks?.onSubmissionError) {
595
598
  await config.hooks.onSubmissionError(
596
- error as Error,
599
+ originalError,
597
600
  slug,
598
601
  data as Record<string, unknown>,
599
602
  submissionContext,
600
603
  );
601
604
  }
602
- throw error;
605
+ throw ctx.error(400, { message: originalError.message });
606
+ }
607
+ if (hookResult && typeof hookResult === "object") {
608
+ finalData = hookResult as Record<string, unknown>;
603
609
  }
604
610
  }
605
611
 
@@ -662,13 +668,11 @@ export const formBuilderBackendPlugin = (
662
668
 
663
669
  // Call before hook for auth check
664
670
  if (config.hooks?.onBeforeListSubmissions) {
665
- const canList = await config.hooks.onBeforeListSubmissions(
666
- formId,
667
- context,
671
+ await runHookWithShim(
672
+ () => config.hooks!.onBeforeListSubmissions!(formId, context),
673
+ ctx.error,
674
+ "Access denied",
668
675
  );
669
- if (!canList) {
670
- throw ctx.error(403, { message: "Access denied" });
671
- }
672
676
  }
673
677
 
674
678
  return getFormSubmissions(adapter, formId, { limit, offset });
@@ -687,13 +691,11 @@ export const formBuilderBackendPlugin = (
687
691
 
688
692
  // Call before hook for access check
689
693
  if (config.hooks?.onBeforeGetSubmission) {
690
- const canGet = await config.hooks.onBeforeGetSubmission(
691
- subId,
692
- context,
694
+ await runHookWithShim(
695
+ () => config.hooks!.onBeforeGetSubmission!(subId, context),
696
+ ctx.error,
697
+ "Access denied",
693
698
  );
694
- if (!canGet) {
695
- throw ctx.error(403, { message: "Access denied" });
696
- }
697
699
  }
698
700
 
699
701
  const submission = await adapter.findOne<FormSubmissionWithForm>({
@@ -731,13 +733,11 @@ export const formBuilderBackendPlugin = (
731
733
 
732
734
  // Call before hook
733
735
  if (config.hooks?.onBeforeSubmissionDeleted) {
734
- const canDelete = await config.hooks.onBeforeSubmissionDeleted(
735
- subId,
736
- context,
736
+ await runHookWithShim(
737
+ () => config.hooks!.onBeforeSubmissionDeleted!(subId, context),
738
+ ctx.error,
739
+ "Delete operation denied",
737
740
  );
738
- if (!canDelete) {
739
- throw ctx.error(403, { message: "Delete operation denied" });
740
- }
741
741
  }
742
742
 
743
743
  await adapter.delete({
@@ -4,6 +4,7 @@ import {
4
4
  defineClientPlugin,
5
5
  createApiClient,
6
6
  isConnectionError,
7
+ runClientHookWithShim,
7
8
  } from "@btst/stack/plugins/client";
8
9
  import { createRoute } from "@btst/yar";
9
10
  import type { QueryClient } from "@tanstack/react-query";
@@ -53,24 +54,24 @@ export interface LoaderContext {
53
54
  */
54
55
  export interface FormBuilderClientHooks {
55
56
  /**
56
- * Called before loading the form list page. Return false to cancel loading.
57
+ * Called before loading the form list page. Throw an error to cancel loading.
57
58
  * @param context - Loader context with path, params, etc.
58
59
  */
59
- beforeLoadFormList?: (context: LoaderContext) => Promise<boolean> | boolean;
60
+ beforeLoadFormList?: (context: LoaderContext) => Promise<void> | void;
60
61
  /**
61
62
  * Called after the form list is loaded.
62
63
  * @param context - Loader context
63
64
  */
64
65
  afterLoadFormList?: (context: LoaderContext) => Promise<void> | void;
65
66
  /**
66
- * Called before loading the form builder page. Return false to cancel loading.
67
+ * Called before loading the form builder page. Throw an error to cancel loading.
67
68
  * @param id - The form ID (undefined for new forms)
68
69
  * @param context - Loader context
69
70
  */
70
71
  beforeLoadFormBuilder?: (
71
72
  id: string | undefined,
72
73
  context: LoaderContext,
73
- ) => Promise<boolean> | boolean;
74
+ ) => Promise<void> | void;
74
75
  /**
75
76
  * Called after the form builder is loaded.
76
77
  * @param id - The form ID (undefined for new forms)
@@ -81,14 +82,14 @@ export interface FormBuilderClientHooks {
81
82
  context: LoaderContext,
82
83
  ) => Promise<void> | void;
83
84
  /**
84
- * Called before loading the submissions page. Return false to cancel loading.
85
+ * Called before loading the submissions page. Throw an error to cancel loading.
85
86
  * @param formId - The form ID
86
87
  * @param context - Loader context
87
88
  */
88
89
  beforeLoadSubmissions?: (
89
90
  formId: string,
90
91
  context: LoaderContext,
91
- ) => Promise<boolean> | boolean;
92
+ ) => Promise<void> | void;
92
93
  /**
93
94
  * Called after the submissions page is loaded.
94
95
  * @param formId - The form ID
@@ -146,10 +147,10 @@ function createFormListLoader(config: FormBuilderClientConfig) {
146
147
  try {
147
148
  // Before hook - authorization check
148
149
  if (hooks?.beforeLoadFormList) {
149
- const canLoad = await hooks.beforeLoadFormList(context);
150
- if (!canLoad) {
151
- throw new Error("Load prevented by beforeLoadFormList hook");
152
- }
150
+ await runClientHookWithShim(
151
+ () => hooks.beforeLoadFormList!(context),
152
+ "Load prevented by beforeLoadFormList hook",
153
+ );
153
154
  }
154
155
 
155
156
  const client = createApiClient<FormBuilderApiRouter>({
@@ -235,10 +236,10 @@ function createFormBuilderLoader(
235
236
  try {
236
237
  // Before hook - authorization check
237
238
  if (hooks?.beforeLoadFormBuilder) {
238
- const canLoad = await hooks.beforeLoadFormBuilder(id, context);
239
- if (!canLoad) {
240
- throw new Error("Load prevented by beforeLoadFormBuilder hook");
241
- }
239
+ await runClientHookWithShim(
240
+ () => hooks.beforeLoadFormBuilder!(id, context),
241
+ "Load prevented by beforeLoadFormBuilder hook",
242
+ );
242
243
  }
243
244
 
244
245
  const client = createApiClient<FormBuilderApiRouter>({
@@ -309,10 +310,10 @@ function createSubmissionsLoader(
309
310
  try {
310
311
  // Before hook - authorization check
311
312
  if (hooks?.beforeLoadSubmissions) {
312
- const canLoad = await hooks.beforeLoadSubmissions(formId, context);
313
- if (!canLoad) {
314
- throw new Error("Load prevented by beforeLoadSubmissions hook");
315
- }
313
+ await runClientHookWithShim(
314
+ () => hooks.beforeLoadSubmissions!(formId, context),
315
+ "Load prevented by beforeLoadSubmissions hook",
316
+ );
316
317
  }
317
318
 
318
319
  const client = createApiClient<FormBuilderApiRouter>({
@@ -167,23 +167,21 @@ export interface FormUpdate {
167
167
  * Backend hooks for Form Builder plugin
168
168
  *
169
169
  * All CRUD hooks receive ipAddress and headers for auth/rate limiting.
170
- * Return false from onBefore* hooks to reject the operation (throws 403).
170
+ * Throw an error from onBefore* hooks to reject the operation (throws 403).
171
171
  */
172
172
  export interface FormBuilderBackendHooks {
173
173
  // ============================================================================
174
174
  // FORM CRUD HOOKS (Admin operations)
175
175
  // ============================================================================
176
176
 
177
- /** Called before listing forms. Return false to deny access (403). */
178
- onBeforeListForms?: (
179
- ctx: FormBuilderHookContext,
180
- ) => Promise<boolean> | boolean;
177
+ /** Called before listing forms. Throw an error to deny access (403). */
178
+ onBeforeListForms?: (ctx: FormBuilderHookContext) => Promise<void> | void;
181
179
 
182
- /** Called before creating a form. Return false to deny, or modified data. */
180
+ /** Called before creating a form. Throw an error to deny, or return modified data. */
183
181
  onBeforeFormCreated?: (
184
182
  data: FormInput,
185
183
  ctx: FormBuilderHookContext,
186
- ) => Promise<FormInput | false> | FormInput | false;
184
+ ) => Promise<FormInput | void> | FormInput | void;
187
185
 
188
186
  /** Called after a form is created */
189
187
  onAfterFormCreated?: (
@@ -191,18 +189,18 @@ export interface FormBuilderBackendHooks {
191
189
  ctx: FormBuilderHookContext,
192
190
  ) => Promise<void> | void;
193
191
 
194
- /** Called before getting a form by ID or slug. Return false to deny access. */
192
+ /** Called before getting a form by ID or slug. Throw an error to deny access. */
195
193
  onBeforeGetForm?: (
196
194
  idOrSlug: string,
197
195
  ctx: FormBuilderHookContext,
198
- ) => Promise<boolean> | boolean;
196
+ ) => Promise<void> | void;
199
197
 
200
- /** Called before updating a form. Return false to deny, or modified data. */
198
+ /** Called before updating a form. Throw an error to deny, or return modified data. */
201
199
  onBeforeFormUpdated?: (
202
200
  id: string,
203
201
  data: FormUpdate,
204
202
  ctx: FormBuilderHookContext,
205
- ) => Promise<FormUpdate | false> | FormUpdate | false;
203
+ ) => Promise<FormUpdate | void> | FormUpdate | void;
206
204
 
207
205
  /** Called after a form is updated */
208
206
  onAfterFormUpdated?: (
@@ -210,11 +208,11 @@ export interface FormBuilderBackendHooks {
210
208
  ctx: FormBuilderHookContext,
211
209
  ) => Promise<void> | void;
212
210
 
213
- /** Called before deleting a form. Return false to deny. */
211
+ /** Called before deleting a form. Throw an error to deny. */
214
212
  onBeforeFormDeleted?: (
215
213
  id: string,
216
214
  ctx: FormBuilderHookContext,
217
- ) => Promise<boolean> | boolean;
215
+ ) => Promise<void> | void;
218
216
 
219
217
  /** Called after a form is deleted */
220
218
  onAfterFormDeleted?: (
@@ -230,16 +228,13 @@ export interface FormBuilderBackendHooks {
230
228
  * Called before processing a form submission.
231
229
  * Use for: spam protection, rate limiting, data validation/enrichment.
232
230
  *
233
- * @returns false to reject submission (400), or modified data to continue
231
+ * Throw an error to reject submission (400), or return modified data to continue.
234
232
  */
235
233
  onBeforeSubmission?: (
236
234
  formSlug: string,
237
235
  data: Record<string, unknown>,
238
236
  ctx: SubmissionHookContext,
239
- ) =>
240
- | Promise<Record<string, unknown> | false>
241
- | Record<string, unknown>
242
- | false;
237
+ ) => Promise<Record<string, unknown> | void> | Record<string, unknown> | void;
243
238
 
244
239
  /**
245
240
  * Called after a submission is saved.
@@ -263,23 +258,23 @@ export interface FormBuilderBackendHooks {
263
258
  // SUBMISSIONS MANAGEMENT HOOKS (Admin viewing submissions)
264
259
  // ============================================================================
265
260
 
266
- /** Called before listing submissions. Return false to deny access (403). */
261
+ /** Called before listing submissions. Throw an error to deny access (403). */
267
262
  onBeforeListSubmissions?: (
268
263
  formId: string,
269
264
  ctx: FormBuilderHookContext,
270
- ) => Promise<boolean> | boolean;
265
+ ) => Promise<void> | void;
271
266
 
272
- /** Called before getting a submission. Return false to deny access. */
267
+ /** Called before getting a submission. Throw an error to deny access. */
273
268
  onBeforeGetSubmission?: (
274
269
  submissionId: string,
275
270
  ctx: FormBuilderHookContext,
276
- ) => Promise<boolean> | boolean;
271
+ ) => Promise<void> | void;
277
272
 
278
- /** Called before deleting a submission. Return false to deny. */
273
+ /** Called before deleting a submission. Throw an error to deny. */
279
274
  onBeforeSubmissionDeleted?: (
280
275
  submissionId: string,
281
276
  ctx: FormBuilderHookContext,
282
- ) => Promise<boolean> | boolean;
277
+ ) => Promise<void> | void;
283
278
 
284
279
  /** Called after a submission is deleted */
285
280
  onAfterSubmissionDeleted?: (