@btst/stack 1.5.2 → 1.7.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 (241) hide show
  1. package/dist/api/index.cjs +7 -1
  2. package/dist/api/index.d.cts +2 -2
  3. package/dist/api/index.d.mts +2 -2
  4. package/dist/api/index.d.ts +2 -2
  5. package/dist/api/index.mjs +7 -1
  6. package/dist/client/index.d.cts +1 -1
  7. package/dist/client/index.d.mts +1 -1
  8. package/dist/client/index.d.ts +1 -1
  9. package/dist/index.d.cts +1 -1
  10. package/dist/index.d.mts +1 -1
  11. package/dist/index.d.ts +1 -1
  12. package/dist/node_modules/.pnpm/@dnd-kit_accessibility@3.1.1_react@19.2.0/node_modules/@dnd-kit/accessibility/dist/accessibility.esm.cjs +68 -0
  13. package/dist/node_modules/.pnpm/@dnd-kit_accessibility@3.1.1_react@19.2.0/node_modules/@dnd-kit/accessibility/dist/accessibility.esm.mjs +60 -0
  14. package/dist/node_modules/.pnpm/@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/@dnd-kit/core/dist/core.esm.cjs +3937 -0
  15. package/dist/node_modules/.pnpm/@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/@dnd-kit/core/dist/core.esm.mjs +3907 -0
  16. package/dist/node_modules/.pnpm/@dnd-kit_modifiers@9.0.0_@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0__react@19.2.0/node_modules/@dnd-kit/modifiers/dist/modifiers.esm.cjs +30 -0
  17. package/dist/node_modules/.pnpm/@dnd-kit_modifiers@9.0.0_@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0__react@19.2.0/node_modules/@dnd-kit/modifiers/dist/modifiers.esm.mjs +28 -0
  18. package/dist/node_modules/.pnpm/@dnd-kit_sortable@10.0.0_@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0__react@19.2.0/node_modules/@dnd-kit/sortable/dist/sortable.esm.cjs +675 -0
  19. package/dist/node_modules/.pnpm/@dnd-kit_sortable@10.0.0_@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0__react@19.2.0/node_modules/@dnd-kit/sortable/dist/sortable.esm.mjs +661 -0
  20. package/dist/node_modules/.pnpm/@dnd-kit_utilities@3.2.2_react@19.2.0/node_modules/@dnd-kit/utilities/dist/utilities.esm.cjs +358 -0
  21. package/dist/node_modules/.pnpm/@dnd-kit_utilities@3.2.2_react@19.2.0/node_modules/@dnd-kit/utilities/dist/utilities.esm.mjs +332 -0
  22. package/dist/node_modules/.pnpm/@radix-ui_react-tabs@1.1.13_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@1_865f042350eb43f3338b0fffb33f6246/node_modules/@radix-ui/react-tabs/dist/index.cjs +211 -0
  23. package/dist/node_modules/.pnpm/@radix-ui_react-tabs@1.1.13_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@1_865f042350eb43f3338b0fffb33f6246/node_modules/@radix-ui/react-tabs/dist/index.mjs +188 -0
  24. package/dist/packages/better-stack/src/plugins/cms/api/plugin.cjs +3 -2
  25. package/dist/packages/better-stack/src/plugins/cms/api/plugin.mjs +3 -2
  26. package/dist/packages/better-stack/src/plugins/cms/client/components/forms/content-form.cjs +15 -15
  27. package/dist/packages/better-stack/src/plugins/cms/client/components/forms/content-form.mjs +16 -16
  28. package/dist/packages/better-stack/src/plugins/form-builder/api/plugin.cjs +588 -0
  29. package/dist/packages/better-stack/src/plugins/form-builder/api/plugin.mjs +586 -0
  30. package/dist/packages/better-stack/src/plugins/form-builder/client/components/forms/form-renderer.cjs +131 -0
  31. package/dist/packages/better-stack/src/plugins/form-builder/client/components/forms/form-renderer.mjs +129 -0
  32. package/dist/packages/better-stack/src/plugins/form-builder/client/components/loading/form-builder-skeleton.cjs +32 -0
  33. package/dist/packages/better-stack/src/plugins/form-builder/client/components/loading/form-builder-skeleton.mjs +30 -0
  34. package/dist/packages/better-stack/src/plugins/form-builder/client/components/loading/form-list-skeleton.cjs +21 -0
  35. package/dist/packages/better-stack/src/plugins/form-builder/client/components/loading/form-list-skeleton.mjs +19 -0
  36. package/dist/packages/better-stack/src/plugins/form-builder/client/components/loading/submissions-skeleton.cjs +34 -0
  37. package/dist/packages/better-stack/src/plugins/form-builder/client/components/loading/submissions-skeleton.mjs +32 -0
  38. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/404-page.cjs +20 -0
  39. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/404-page.mjs +18 -0
  40. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/form-builder-page.cjs +19 -0
  41. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/form-builder-page.internal.cjs +186 -0
  42. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/form-builder-page.internal.mjs +184 -0
  43. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/form-builder-page.mjs +17 -0
  44. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/form-list-page.cjs +19 -0
  45. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/form-list-page.internal.cjs +165 -0
  46. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/form-list-page.internal.mjs +163 -0
  47. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/form-list-page.mjs +17 -0
  48. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/submissions-page.cjs +19 -0
  49. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/submissions-page.internal.cjs +177 -0
  50. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/submissions-page.internal.mjs +175 -0
  51. package/dist/packages/better-stack/src/plugins/form-builder/client/components/pages/submissions-page.mjs +17 -0
  52. package/dist/packages/better-stack/src/plugins/form-builder/client/components/shared/default-error.cjs +17 -0
  53. package/dist/packages/better-stack/src/plugins/form-builder/client/components/shared/default-error.mjs +15 -0
  54. package/dist/packages/better-stack/src/plugins/form-builder/client/components/shared/empty-state.cjs +16 -0
  55. package/dist/packages/better-stack/src/plugins/form-builder/client/components/shared/empty-state.mjs +14 -0
  56. package/dist/packages/better-stack/src/plugins/form-builder/client/components/shared/page-wrapper.cjs +27 -0
  57. package/dist/packages/better-stack/src/plugins/form-builder/client/components/shared/page-wrapper.mjs +25 -0
  58. package/dist/packages/better-stack/src/plugins/form-builder/client/components/shared/pagination.cjs +39 -0
  59. package/dist/packages/better-stack/src/plugins/form-builder/client/components/shared/pagination.mjs +37 -0
  60. package/dist/packages/better-stack/src/plugins/form-builder/client/hooks/form-builder-hooks.cjs +551 -0
  61. package/dist/packages/better-stack/src/plugins/form-builder/client/hooks/form-builder-hooks.mjs +537 -0
  62. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/form-builder-common.cjs +36 -0
  63. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/form-builder-common.mjs +34 -0
  64. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/form-builder-editor.cjs +19 -0
  65. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/form-builder-editor.mjs +17 -0
  66. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/form-builder-list.cjs +21 -0
  67. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/form-builder-list.mjs +19 -0
  68. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/form-builder-submissions.cjs +19 -0
  69. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/form-builder-submissions.mjs +17 -0
  70. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/form-builder-toasts.cjs +14 -0
  71. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/form-builder-toasts.mjs +12 -0
  72. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/index.cjs +17 -0
  73. package/dist/packages/better-stack/src/plugins/form-builder/client/localization/index.mjs +15 -0
  74. package/dist/packages/better-stack/src/plugins/form-builder/client/plugin.cjs +278 -0
  75. package/dist/packages/better-stack/src/plugins/form-builder/client/plugin.mjs +276 -0
  76. package/dist/packages/better-stack/src/plugins/form-builder/db.cjs +99 -0
  77. package/dist/packages/better-stack/src/plugins/form-builder/db.mjs +97 -0
  78. package/dist/packages/better-stack/src/plugins/form-builder/schemas.cjs +82 -0
  79. package/dist/packages/better-stack/src/plugins/form-builder/schemas.mjs +74 -0
  80. package/dist/packages/better-stack/src/plugins/form-builder/utils.cjs +37 -0
  81. package/dist/packages/better-stack/src/plugins/form-builder/utils.mjs +29 -0
  82. package/dist/packages/better-stack/src/plugins/open-api/api/generator.cjs +300 -0
  83. package/dist/packages/better-stack/src/plugins/open-api/api/generator.mjs +284 -0
  84. package/dist/packages/better-stack/src/plugins/open-api/api/plugin.cjs +115 -0
  85. package/dist/packages/better-stack/src/plugins/open-api/api/plugin.mjs +113 -0
  86. package/dist/packages/better-stack/src/plugins/open-api/db.cjs +7 -0
  87. package/dist/packages/better-stack/src/plugins/open-api/db.mjs +5 -0
  88. package/dist/packages/better-stack/src/plugins/open-api/logo.cjs +8 -0
  89. package/dist/packages/better-stack/src/plugins/open-api/logo.mjs +6 -0
  90. package/dist/packages/ui/src/components/auto-form/index.cjs +2 -12
  91. package/dist/packages/ui/src/components/auto-form/index.mjs +2 -9
  92. package/dist/packages/ui/src/components/auto-form/stepped-auto-form.cjs +377 -0
  93. package/dist/packages/ui/src/components/auto-form/stepped-auto-form.mjs +368 -0
  94. package/dist/packages/ui/src/components/auto-form/utils.cjs +1 -56
  95. package/dist/packages/ui/src/components/auto-form/utils.mjs +2 -56
  96. package/dist/packages/ui/src/components/form-builder/canvas.cjs +111 -0
  97. package/dist/packages/ui/src/components/form-builder/canvas.mjs +109 -0
  98. package/dist/packages/ui/src/components/form-builder/components/index.cjs +570 -0
  99. package/dist/packages/ui/src/components/form-builder/components/index.mjs +553 -0
  100. package/dist/packages/ui/src/components/form-builder/edit-field-dialog.cjs +131 -0
  101. package/dist/packages/ui/src/components/form-builder/edit-field-dialog.mjs +129 -0
  102. package/dist/packages/ui/src/components/form-builder/form-preview.cjs +73 -0
  103. package/dist/packages/ui/src/components/form-builder/form-preview.mjs +71 -0
  104. package/dist/packages/ui/src/components/form-builder/index.cjs +353 -0
  105. package/dist/packages/ui/src/components/form-builder/index.mjs +344 -0
  106. package/dist/packages/ui/src/components/form-builder/nested-field-editor-dialog.cjs +263 -0
  107. package/dist/packages/ui/src/components/form-builder/nested-field-editor-dialog.mjs +261 -0
  108. package/dist/packages/ui/src/components/form-builder/palette.cjs +52 -0
  109. package/dist/packages/ui/src/components/form-builder/palette.mjs +49 -0
  110. package/dist/packages/ui/src/components/form-builder/schema-utils.cjs +120 -0
  111. package/dist/packages/ui/src/components/form-builder/schema-utils.mjs +114 -0
  112. package/dist/packages/ui/src/components/form-builder/sortable-field.cjs +151 -0
  113. package/dist/packages/ui/src/components/form-builder/sortable-field.mjs +148 -0
  114. package/dist/packages/ui/src/components/form-builder/step-tabs.cjs +180 -0
  115. package/dist/packages/ui/src/components/form-builder/step-tabs.mjs +178 -0
  116. package/dist/packages/ui/src/components/form-builder/types.cjs +7 -0
  117. package/dist/packages/ui/src/components/form-builder/types.mjs +5 -0
  118. package/dist/packages/ui/src/components/form-builder/validation-schemas.cjs +67 -0
  119. package/dist/packages/ui/src/components/form-builder/validation-schemas.mjs +56 -0
  120. package/dist/packages/ui/src/components/tabs.cjs +70 -0
  121. package/dist/packages/ui/src/components/tabs.mjs +65 -0
  122. package/dist/packages/ui/src/lib/schema-converter.cjs +130 -0
  123. package/dist/packages/ui/src/lib/schema-converter.mjs +124 -0
  124. package/dist/plugins/api/index.d.cts +2 -2
  125. package/dist/plugins/api/index.d.mts +2 -2
  126. package/dist/plugins/api/index.d.ts +2 -2
  127. package/dist/plugins/blog/api/index.d.cts +1 -1
  128. package/dist/plugins/blog/api/index.d.mts +1 -1
  129. package/dist/plugins/blog/api/index.d.ts +1 -1
  130. package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
  131. package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
  132. package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
  133. package/dist/plugins/blog/client/index.d.cts +1 -1
  134. package/dist/plugins/blog/client/index.d.mts +1 -1
  135. package/dist/plugins/blog/client/index.d.ts +1 -1
  136. package/dist/plugins/blog/query-keys.d.cts +2 -2
  137. package/dist/plugins/blog/query-keys.d.mts +2 -2
  138. package/dist/plugins/blog/query-keys.d.ts +2 -2
  139. package/dist/plugins/client/index.d.cts +2 -2
  140. package/dist/plugins/client/index.d.mts +2 -2
  141. package/dist/plugins/client/index.d.ts +2 -2
  142. package/dist/plugins/cms/client/index.cjs +6 -0
  143. package/dist/plugins/cms/client/index.d.cts +6 -113
  144. package/dist/plugins/cms/client/index.d.mts +6 -113
  145. package/dist/plugins/cms/client/index.d.ts +6 -113
  146. package/dist/plugins/cms/client/index.mjs +1 -0
  147. package/dist/plugins/form-builder/api/index.cjs +7 -0
  148. package/dist/plugins/form-builder/api/index.d.cts +141 -0
  149. package/dist/plugins/form-builder/api/index.d.mts +141 -0
  150. package/dist/plugins/form-builder/api/index.d.ts +141 -0
  151. package/dist/plugins/form-builder/api/index.mjs +1 -0
  152. package/dist/plugins/form-builder/client/components/index.cjs +29 -0
  153. package/dist/plugins/form-builder/client/components/index.d.cts +93 -0
  154. package/dist/plugins/form-builder/client/components/index.d.mts +93 -0
  155. package/dist/plugins/form-builder/client/components/index.d.ts +93 -0
  156. package/dist/plugins/form-builder/client/components/index.mjs +18 -0
  157. package/dist/plugins/form-builder/client/hooks/index.cjs +19 -0
  158. package/dist/plugins/form-builder/client/hooks/index.d.cts +154 -0
  159. package/dist/plugins/form-builder/client/hooks/index.d.mts +154 -0
  160. package/dist/plugins/form-builder/client/hooks/index.d.ts +154 -0
  161. package/dist/plugins/form-builder/client/hooks/index.mjs +1 -0
  162. package/dist/plugins/form-builder/client/index.cjs +13 -0
  163. package/dist/plugins/form-builder/client/index.d.cts +381 -0
  164. package/dist/plugins/form-builder/client/index.d.mts +381 -0
  165. package/dist/plugins/form-builder/client/index.d.ts +381 -0
  166. package/dist/plugins/form-builder/client/index.mjs +2 -0
  167. package/dist/plugins/form-builder/client.css +3 -0
  168. package/dist/plugins/form-builder/query-keys.cjs +143 -0
  169. package/dist/plugins/form-builder/query-keys.d.cts +74 -0
  170. package/dist/plugins/form-builder/query-keys.d.mts +74 -0
  171. package/dist/plugins/form-builder/query-keys.d.ts +74 -0
  172. package/dist/plugins/form-builder/query-keys.mjs +141 -0
  173. package/dist/plugins/form-builder/style.css +19 -0
  174. package/dist/plugins/open-api/api/index.cjs +9 -0
  175. package/dist/plugins/open-api/api/index.d.cts +95 -0
  176. package/dist/plugins/open-api/api/index.d.mts +95 -0
  177. package/dist/plugins/open-api/api/index.d.ts +95 -0
  178. package/dist/plugins/open-api/api/index.mjs +2 -0
  179. package/dist/shared/stack.AX5nZ6A3.d.cts +86 -0
  180. package/dist/shared/stack.AX5nZ6A3.d.mts +86 -0
  181. package/dist/shared/stack.AX5nZ6A3.d.ts +86 -0
  182. package/dist/shared/stack.BIh2AXaW.d.cts +123 -0
  183. package/dist/shared/stack.BIh2AXaW.d.mts +123 -0
  184. package/dist/shared/stack.BIh2AXaW.d.ts +123 -0
  185. package/dist/shared/{stack.ByOugz9d.d.cts → stack.CSce37mX.d.cts} +15 -2
  186. package/dist/shared/{stack.ByOugz9d.d.mts → stack.CSce37mX.d.mts} +15 -2
  187. package/dist/shared/{stack.ByOugz9d.d.ts → stack.CSce37mX.d.ts} +15 -2
  188. package/dist/shared/stack.DzH_wcvr.d.cts +195 -0
  189. package/dist/shared/stack.DzH_wcvr.d.mts +195 -0
  190. package/dist/shared/stack.DzH_wcvr.d.ts +195 -0
  191. package/package.json +67 -1
  192. package/src/api/index.ts +14 -2
  193. package/src/plugins/cms/api/plugin.ts +9 -4
  194. package/src/plugins/cms/client/components/forms/content-form.tsx +23 -25
  195. package/src/plugins/cms/client/index.ts +11 -0
  196. package/src/plugins/form-builder/api/index.ts +1 -0
  197. package/src/plugins/form-builder/api/plugin.ts +776 -0
  198. package/src/plugins/form-builder/client/components/forms/form-renderer.tsx +253 -0
  199. package/src/plugins/form-builder/client/components/index.tsx +24 -0
  200. package/src/plugins/form-builder/client/components/loading/form-builder-skeleton.tsx +42 -0
  201. package/src/plugins/form-builder/client/components/loading/form-list-skeleton.tsx +25 -0
  202. package/src/plugins/form-builder/client/components/loading/index.tsx +3 -0
  203. package/src/plugins/form-builder/client/components/loading/submissions-skeleton.tsx +40 -0
  204. package/src/plugins/form-builder/client/components/pages/404-page.tsx +28 -0
  205. package/src/plugins/form-builder/client/components/pages/form-builder-page.internal.tsx +253 -0
  206. package/src/plugins/form-builder/client/components/pages/form-builder-page.tsx +26 -0
  207. package/src/plugins/form-builder/client/components/pages/form-list-page.internal.tsx +231 -0
  208. package/src/plugins/form-builder/client/components/pages/form-list-page.tsx +22 -0
  209. package/src/plugins/form-builder/client/components/pages/submissions-page.internal.tsx +268 -0
  210. package/src/plugins/form-builder/client/components/pages/submissions-page.tsx +26 -0
  211. package/src/plugins/form-builder/client/components/shared/default-error.tsx +30 -0
  212. package/src/plugins/form-builder/client/components/shared/empty-state.tsx +26 -0
  213. package/src/plugins/form-builder/client/components/shared/page-wrapper.tsx +32 -0
  214. package/src/plugins/form-builder/client/components/shared/pagination.tsx +52 -0
  215. package/src/plugins/form-builder/client/hooks/form-builder-hooks.tsx +799 -0
  216. package/src/plugins/form-builder/client/hooks/index.tsx +1 -0
  217. package/src/plugins/form-builder/client/index.ts +22 -0
  218. package/src/plugins/form-builder/client/localization/form-builder-common.ts +36 -0
  219. package/src/plugins/form-builder/client/localization/form-builder-editor.ts +18 -0
  220. package/src/plugins/form-builder/client/localization/form-builder-list.ts +17 -0
  221. package/src/plugins/form-builder/client/localization/form-builder-submissions.ts +17 -0
  222. package/src/plugins/form-builder/client/localization/form-builder-toasts.ts +10 -0
  223. package/src/plugins/form-builder/client/localization/index.ts +15 -0
  224. package/src/plugins/form-builder/client/overrides.ts +146 -0
  225. package/src/plugins/form-builder/client/plugin.tsx +488 -0
  226. package/src/plugins/form-builder/client.css +3 -0
  227. package/src/plugins/form-builder/db.ts +99 -0
  228. package/src/plugins/form-builder/query-keys.ts +198 -0
  229. package/src/plugins/form-builder/schemas.ts +122 -0
  230. package/src/plugins/form-builder/style.css +19 -0
  231. package/src/plugins/form-builder/types.ts +317 -0
  232. package/src/plugins/form-builder/utils.ts +63 -0
  233. package/src/plugins/open-api/api/generator.ts +433 -0
  234. package/src/plugins/open-api/api/index.ts +8 -0
  235. package/src/plugins/open-api/api/plugin.ts +243 -0
  236. package/src/plugins/open-api/db.ts +7 -0
  237. package/src/plugins/open-api/logo.ts +7 -0
  238. package/src/types.ts +15 -1
  239. package/dist/shared/{stack.DLhzx1-D.d.mts → stack.CcI4sYJP.d.cts} +1 -1
  240. package/dist/shared/{stack.DLhzx1-D.d.ts → stack.CcI4sYJP.d.mts} +1 -1
  241. package/dist/shared/{stack.DLhzx1-D.d.cts → stack.CcI4sYJP.d.ts} +1 -1
@@ -0,0 +1,586 @@
1
+ import { defineBackendPlugin, createEndpoint } from '@btst/stack/plugins/api';
2
+ import { z } from 'zod';
3
+ import { formSchemaToZod } from '../../../../../ui/src/lib/schema-converter.mjs';
4
+ import { formBuilderSchema } from '../db.mjs';
5
+ import { listFormsQuerySchema, createFormSchema, updateFormSchema, listSubmissionsQuerySchema } from '../schemas.mjs';
6
+ import { extractUserAgent, extractIpAddress, slugify } from '../utils.mjs';
7
+
8
+ function serializeForm(form) {
9
+ return {
10
+ id: form.id,
11
+ name: form.name,
12
+ slug: form.slug,
13
+ description: form.description,
14
+ schema: form.schema,
15
+ successMessage: form.successMessage,
16
+ redirectUrl: form.redirectUrl,
17
+ status: form.status,
18
+ createdBy: form.createdBy,
19
+ createdAt: form.createdAt.toISOString(),
20
+ updatedAt: form.updatedAt.toISOString()
21
+ };
22
+ }
23
+ function serializeFormSubmission(submission) {
24
+ return {
25
+ ...submission,
26
+ submittedAt: submission.submittedAt.toISOString()
27
+ };
28
+ }
29
+ function serializeFormSubmissionWithData(submission) {
30
+ return {
31
+ ...serializeFormSubmission(submission),
32
+ parsedData: JSON.parse(submission.data),
33
+ form: submission.form ? serializeForm(submission.form) : void 0
34
+ };
35
+ }
36
+ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
37
+ name: "form-builder",
38
+ dbPlugin: formBuilderSchema,
39
+ routes: (adapter) => {
40
+ const createContext = (headers) => ({
41
+ headers,
42
+ ipAddress: extractIpAddress(headers),
43
+ userAgent: extractUserAgent(headers)
44
+ });
45
+ const createSubmissionContext = (formSlug, formId, headers) => ({
46
+ ...createContext(headers),
47
+ formSlug,
48
+ formId
49
+ });
50
+ const listForms = createEndpoint(
51
+ "/forms",
52
+ {
53
+ method: "GET",
54
+ query: listFormsQuerySchema
55
+ },
56
+ async (ctx) => {
57
+ const { status, limit, offset } = ctx.query;
58
+ const context = createContext(ctx.headers);
59
+ if (config.hooks?.onBeforeListForms) {
60
+ const canList = await config.hooks.onBeforeListForms(context);
61
+ if (!canList) {
62
+ throw ctx.error(403, { message: "Access denied" });
63
+ }
64
+ }
65
+ const whereConditions = [];
66
+ if (status) {
67
+ whereConditions.push({
68
+ field: "status",
69
+ value: status,
70
+ operator: "eq"
71
+ });
72
+ }
73
+ const allForms = await adapter.findMany({
74
+ model: "form",
75
+ where: whereConditions.length > 0 ? whereConditions : void 0
76
+ });
77
+ const total = allForms.length;
78
+ const forms = await adapter.findMany({
79
+ model: "form",
80
+ where: whereConditions.length > 0 ? whereConditions : void 0,
81
+ limit,
82
+ offset,
83
+ sortBy: { field: "createdAt", direction: "desc" }
84
+ });
85
+ return {
86
+ items: forms.map(serializeForm),
87
+ total,
88
+ limit,
89
+ offset
90
+ };
91
+ }
92
+ );
93
+ const getFormBySlug = createEndpoint(
94
+ "/forms/:slug",
95
+ {
96
+ method: "GET",
97
+ params: z.object({ slug: z.string() })
98
+ },
99
+ async (ctx) => {
100
+ const { slug } = ctx.params;
101
+ const context = createContext(ctx.headers);
102
+ if (config.hooks?.onBeforeGetForm) {
103
+ const canGet = await config.hooks.onBeforeGetForm(slug, context);
104
+ if (!canGet) {
105
+ throw ctx.error(403, { message: "Access denied" });
106
+ }
107
+ }
108
+ const form = await adapter.findOne({
109
+ model: "form",
110
+ where: [{ field: "slug", value: slug, operator: "eq" }]
111
+ });
112
+ if (!form) {
113
+ throw ctx.error(404, { message: "Form not found" });
114
+ }
115
+ return serializeForm(form);
116
+ }
117
+ );
118
+ const getFormById = createEndpoint(
119
+ "/forms/id/:id",
120
+ {
121
+ method: "GET",
122
+ params: z.object({ id: z.string() })
123
+ },
124
+ async (ctx) => {
125
+ const { id } = ctx.params;
126
+ const context = createContext(ctx.headers);
127
+ if (config.hooks?.onBeforeGetForm) {
128
+ const canGet = await config.hooks.onBeforeGetForm(id, context);
129
+ if (!canGet) {
130
+ throw ctx.error(403, { message: "Access denied" });
131
+ }
132
+ }
133
+ const form = await adapter.findOne({
134
+ model: "form",
135
+ where: [{ field: "id", value: id, operator: "eq" }]
136
+ });
137
+ if (!form) {
138
+ throw ctx.error(404, { message: "Form not found" });
139
+ }
140
+ return serializeForm(form);
141
+ }
142
+ );
143
+ const createForm = createEndpoint(
144
+ "/forms",
145
+ {
146
+ method: "POST",
147
+ body: createFormSchema
148
+ },
149
+ async (ctx) => {
150
+ const body = ctx.body;
151
+ const context = createContext(ctx.headers);
152
+ const slug = slugify(body.slug);
153
+ if (!slug) {
154
+ throw ctx.error(400, {
155
+ message: "Invalid slug: must contain at least one alphanumeric character"
156
+ });
157
+ }
158
+ const existing = await adapter.findOne({
159
+ model: "form",
160
+ where: [{ field: "slug", value: slug, operator: "eq" }]
161
+ });
162
+ if (existing) {
163
+ throw ctx.error(409, {
164
+ message: "Form with this slug already exists"
165
+ });
166
+ }
167
+ try {
168
+ JSON.parse(body.schema);
169
+ } catch {
170
+ throw ctx.error(400, { message: "Invalid JSON Schema" });
171
+ }
172
+ let formInput = {
173
+ name: body.name,
174
+ slug,
175
+ description: body.description,
176
+ schema: body.schema,
177
+ successMessage: body.successMessage,
178
+ redirectUrl: body.redirectUrl || void 0,
179
+ status: body.status
180
+ };
181
+ if (config.hooks?.onBeforeFormCreated) {
182
+ const result = await config.hooks.onBeforeFormCreated(
183
+ formInput,
184
+ context
185
+ );
186
+ if (result === false) {
187
+ throw ctx.error(403, { message: "Create operation denied" });
188
+ }
189
+ if (result && typeof result === "object") {
190
+ formInput = result;
191
+ }
192
+ }
193
+ const form = await adapter.create({
194
+ model: "form",
195
+ data: {
196
+ name: formInput.name,
197
+ slug: formInput.slug,
198
+ description: formInput.description,
199
+ schema: formInput.schema,
200
+ successMessage: formInput.successMessage,
201
+ redirectUrl: formInput.redirectUrl,
202
+ status: formInput.status || "active",
203
+ createdBy: formInput.createdBy,
204
+ createdAt: /* @__PURE__ */ new Date(),
205
+ updatedAt: /* @__PURE__ */ new Date()
206
+ }
207
+ });
208
+ const serialized = serializeForm(form);
209
+ if (config.hooks?.onAfterFormCreated) {
210
+ await config.hooks.onAfterFormCreated(serialized, context);
211
+ }
212
+ return serialized;
213
+ }
214
+ );
215
+ const updateForm = createEndpoint(
216
+ "/forms/:id",
217
+ {
218
+ method: "PUT",
219
+ params: z.object({ id: z.string() }),
220
+ body: updateFormSchema
221
+ },
222
+ async (ctx) => {
223
+ const { id } = ctx.params;
224
+ const body = ctx.body;
225
+ const context = createContext(ctx.headers);
226
+ const existing = await adapter.findOne({
227
+ model: "form",
228
+ where: [{ field: "id", value: id, operator: "eq" }]
229
+ });
230
+ if (!existing) {
231
+ throw ctx.error(404, { message: "Form not found" });
232
+ }
233
+ let slug;
234
+ if (body.slug) {
235
+ slug = slugify(body.slug);
236
+ if (!slug) {
237
+ throw ctx.error(400, {
238
+ message: "Invalid slug: must contain at least one alphanumeric character"
239
+ });
240
+ }
241
+ if (slug !== existing.slug) {
242
+ const duplicate = await adapter.findOne({
243
+ model: "form",
244
+ where: [
245
+ { field: "slug", value: slug, operator: "eq" }
246
+ ]
247
+ });
248
+ if (duplicate) {
249
+ throw ctx.error(409, {
250
+ message: "Form with this slug already exists"
251
+ });
252
+ }
253
+ }
254
+ }
255
+ if (body.schema) {
256
+ try {
257
+ JSON.parse(body.schema);
258
+ } catch {
259
+ throw ctx.error(400, { message: "Invalid JSON Schema" });
260
+ }
261
+ }
262
+ let updateInput = {
263
+ name: body.name,
264
+ slug,
265
+ description: body.description,
266
+ schema: body.schema,
267
+ successMessage: body.successMessage,
268
+ redirectUrl: body.redirectUrl,
269
+ status: body.status
270
+ };
271
+ if (config.hooks?.onBeforeFormUpdated) {
272
+ const result = await config.hooks.onBeforeFormUpdated(
273
+ id,
274
+ updateInput,
275
+ context
276
+ );
277
+ if (result === false) {
278
+ throw ctx.error(403, { message: "Update operation denied" });
279
+ }
280
+ if (result && typeof result === "object") {
281
+ updateInput = result;
282
+ }
283
+ }
284
+ const updateData = {
285
+ updatedAt: /* @__PURE__ */ new Date()
286
+ };
287
+ if (updateInput.name) updateData.name = updateInput.name;
288
+ if (updateInput.slug) updateData.slug = updateInput.slug;
289
+ if (updateInput.description !== void 0)
290
+ updateData.description = updateInput.description;
291
+ if (updateInput.schema) updateData.schema = updateInput.schema;
292
+ if (updateInput.successMessage !== void 0)
293
+ updateData.successMessage = updateInput.successMessage;
294
+ if (updateInput.redirectUrl !== void 0)
295
+ updateData.redirectUrl = updateInput.redirectUrl;
296
+ if (updateInput.status) updateData.status = updateInput.status;
297
+ await adapter.update({
298
+ model: "form",
299
+ where: [{ field: "id", value: id, operator: "eq" }],
300
+ update: updateData
301
+ });
302
+ const updated = await adapter.findOne({
303
+ model: "form",
304
+ where: [{ field: "id", value: id, operator: "eq" }]
305
+ });
306
+ if (!updated) {
307
+ throw ctx.error(500, { message: "Failed to fetch updated form" });
308
+ }
309
+ const serialized = serializeForm(updated);
310
+ if (config.hooks?.onAfterFormUpdated) {
311
+ await config.hooks.onAfterFormUpdated(serialized, context);
312
+ }
313
+ return serialized;
314
+ }
315
+ );
316
+ const deleteForm = createEndpoint(
317
+ "/forms/:id",
318
+ {
319
+ method: "DELETE",
320
+ params: z.object({ id: z.string() })
321
+ },
322
+ async (ctx) => {
323
+ const { id } = ctx.params;
324
+ const context = createContext(ctx.headers);
325
+ const existing = await adapter.findOne({
326
+ model: "form",
327
+ where: [{ field: "id", value: id, operator: "eq" }]
328
+ });
329
+ if (!existing) {
330
+ throw ctx.error(404, { message: "Form not found" });
331
+ }
332
+ if (config.hooks?.onBeforeFormDeleted) {
333
+ const canDelete = await config.hooks.onBeforeFormDeleted(
334
+ id,
335
+ context
336
+ );
337
+ if (!canDelete) {
338
+ throw ctx.error(403, { message: "Delete operation denied" });
339
+ }
340
+ }
341
+ await adapter.delete({
342
+ model: "formSubmission",
343
+ where: [{ field: "formId", value: id, operator: "eq" }]
344
+ });
345
+ await adapter.delete({
346
+ model: "form",
347
+ where: [{ field: "id", value: id, operator: "eq" }]
348
+ });
349
+ if (config.hooks?.onAfterFormDeleted) {
350
+ await config.hooks.onAfterFormDeleted(id, context);
351
+ }
352
+ return { success: true };
353
+ }
354
+ );
355
+ const submitForm = createEndpoint(
356
+ "/forms/:slug/submit",
357
+ {
358
+ method: "POST",
359
+ params: z.object({ slug: z.string() }),
360
+ body: z.object({
361
+ // Use passthrough object for dynamic form data
362
+ data: z.object({}).passthrough()
363
+ })
364
+ },
365
+ async (ctx) => {
366
+ const { slug } = ctx.params;
367
+ const { data } = ctx.body;
368
+ const baseContext = createContext(ctx.headers);
369
+ const form = await adapter.findOne({
370
+ model: "form",
371
+ where: [{ field: "slug", value: slug, operator: "eq" }]
372
+ });
373
+ if (!form) {
374
+ throw ctx.error(404, { message: "Form not found" });
375
+ }
376
+ if (form.status !== "active") {
377
+ throw ctx.error(400, {
378
+ message: "Form is not accepting submissions"
379
+ });
380
+ }
381
+ const submissionContext = createSubmissionContext(
382
+ slug,
383
+ form.id,
384
+ ctx.headers
385
+ );
386
+ try {
387
+ const jsonSchema = JSON.parse(form.schema);
388
+ const zodSchema = formSchemaToZod(jsonSchema);
389
+ const validation = zodSchema.safeParse(data);
390
+ if (!validation.success) {
391
+ throw ctx.error(400, {
392
+ message: "Validation failed",
393
+ errors: validation.error.issues
394
+ });
395
+ }
396
+ } catch (error) {
397
+ if (error && typeof error === "object" && "code" in error) {
398
+ throw error;
399
+ }
400
+ throw ctx.error(400, { message: "Invalid form data" });
401
+ }
402
+ let finalData = data;
403
+ if (config.hooks?.onBeforeSubmission) {
404
+ try {
405
+ const result = await config.hooks.onBeforeSubmission(
406
+ slug,
407
+ data,
408
+ submissionContext
409
+ );
410
+ if (result === false) {
411
+ throw ctx.error(400, { message: "Submission rejected" });
412
+ }
413
+ if (result && typeof result === "object") {
414
+ finalData = result;
415
+ }
416
+ } catch (error) {
417
+ if (config.hooks?.onSubmissionError) {
418
+ await config.hooks.onSubmissionError(
419
+ error,
420
+ slug,
421
+ data,
422
+ submissionContext
423
+ );
424
+ }
425
+ throw error;
426
+ }
427
+ }
428
+ const submission = await adapter.create({
429
+ model: "formSubmission",
430
+ data: {
431
+ formId: form.id,
432
+ data: JSON.stringify(finalData),
433
+ submittedAt: /* @__PURE__ */ new Date(),
434
+ ipAddress: baseContext.ipAddress,
435
+ userAgent: baseContext.userAgent
436
+ }
437
+ });
438
+ const serialized = serializeFormSubmission(submission);
439
+ if (config.hooks?.onAfterSubmission) {
440
+ await config.hooks.onAfterSubmission(
441
+ serialized,
442
+ serializeForm(form),
443
+ submissionContext
444
+ );
445
+ }
446
+ return {
447
+ ...serialized,
448
+ form: {
449
+ successMessage: form.successMessage,
450
+ redirectUrl: form.redirectUrl
451
+ }
452
+ };
453
+ }
454
+ );
455
+ const listSubmissions = createEndpoint(
456
+ "/forms/:formId/submissions",
457
+ {
458
+ method: "GET",
459
+ params: z.object({ formId: z.string() }),
460
+ query: listSubmissionsQuerySchema
461
+ },
462
+ async (ctx) => {
463
+ const { formId } = ctx.params;
464
+ const { limit, offset } = ctx.query;
465
+ const context = createContext(ctx.headers);
466
+ const form = await adapter.findOne({
467
+ model: "form",
468
+ where: [{ field: "id", value: formId, operator: "eq" }]
469
+ });
470
+ if (!form) {
471
+ throw ctx.error(404, { message: "Form not found" });
472
+ }
473
+ if (config.hooks?.onBeforeListSubmissions) {
474
+ const canList = await config.hooks.onBeforeListSubmissions(
475
+ formId,
476
+ context
477
+ );
478
+ if (!canList) {
479
+ throw ctx.error(403, { message: "Access denied" });
480
+ }
481
+ }
482
+ const allSubmissions = await adapter.findMany({
483
+ model: "formSubmission",
484
+ where: [
485
+ { field: "formId", value: formId, operator: "eq" }
486
+ ]
487
+ });
488
+ const total = allSubmissions.length;
489
+ const submissions = await adapter.findMany({
490
+ model: "formSubmission",
491
+ where: [
492
+ { field: "formId", value: formId, operator: "eq" }
493
+ ],
494
+ limit,
495
+ offset,
496
+ sortBy: { field: "submittedAt", direction: "desc" },
497
+ join: { form: true }
498
+ });
499
+ return {
500
+ items: submissions.map(serializeFormSubmissionWithData),
501
+ total,
502
+ limit,
503
+ offset
504
+ };
505
+ }
506
+ );
507
+ const getSubmission = createEndpoint(
508
+ "/forms/:formId/submissions/:subId",
509
+ {
510
+ method: "GET",
511
+ params: z.object({ formId: z.string(), subId: z.string() })
512
+ },
513
+ async (ctx) => {
514
+ const { formId, subId } = ctx.params;
515
+ const context = createContext(ctx.headers);
516
+ if (config.hooks?.onBeforeGetSubmission) {
517
+ const canGet = await config.hooks.onBeforeGetSubmission(
518
+ subId,
519
+ context
520
+ );
521
+ if (!canGet) {
522
+ throw ctx.error(403, { message: "Access denied" });
523
+ }
524
+ }
525
+ const submission = await adapter.findOne({
526
+ model: "formSubmission",
527
+ where: [{ field: "id", value: subId, operator: "eq" }],
528
+ join: { form: true }
529
+ });
530
+ if (!submission || submission.formId !== formId) {
531
+ throw ctx.error(404, { message: "Submission not found" });
532
+ }
533
+ return serializeFormSubmissionWithData(submission);
534
+ }
535
+ );
536
+ const deleteSubmission = createEndpoint(
537
+ "/forms/:formId/submissions/:subId",
538
+ {
539
+ method: "DELETE",
540
+ params: z.object({ formId: z.string(), subId: z.string() })
541
+ },
542
+ async (ctx) => {
543
+ const { formId, subId } = ctx.params;
544
+ const context = createContext(ctx.headers);
545
+ const existing = await adapter.findOne({
546
+ model: "formSubmission",
547
+ where: [{ field: "id", value: subId, operator: "eq" }]
548
+ });
549
+ if (!existing || existing.formId !== formId) {
550
+ throw ctx.error(404, { message: "Submission not found" });
551
+ }
552
+ if (config.hooks?.onBeforeSubmissionDeleted) {
553
+ const canDelete = await config.hooks.onBeforeSubmissionDeleted(
554
+ subId,
555
+ context
556
+ );
557
+ if (!canDelete) {
558
+ throw ctx.error(403, { message: "Delete operation denied" });
559
+ }
560
+ }
561
+ await adapter.delete({
562
+ model: "formSubmission",
563
+ where: [{ field: "id", value: subId, operator: "eq" }]
564
+ });
565
+ if (config.hooks?.onAfterSubmissionDeleted) {
566
+ await config.hooks.onAfterSubmissionDeleted(subId, context);
567
+ }
568
+ return { success: true };
569
+ }
570
+ );
571
+ return {
572
+ listForms,
573
+ getFormBySlug,
574
+ getFormById,
575
+ createForm,
576
+ updateForm,
577
+ deleteForm,
578
+ submitForm,
579
+ listSubmissions,
580
+ getSubmission,
581
+ deleteSubmission
582
+ };
583
+ }
584
+ });
585
+
586
+ export { formBuilderBackendPlugin };