@btst/stack 2.2.0 → 2.4.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 (237) 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 +54 -7
  6. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +54 -7
  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/schemas.cjs +17 -1
  16. package/dist/packages/stack/src/plugins/ai-chat/schemas.mjs +17 -1
  17. package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +52 -1
  18. package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +52 -1
  19. package/dist/packages/stack/src/plugins/blog/api/query-key-defs.cjs +18 -0
  20. package/dist/packages/stack/src/plugins/blog/api/query-key-defs.mjs +15 -0
  21. package/dist/packages/stack/src/plugins/blog/api/serializers.cjs +21 -0
  22. package/dist/packages/stack/src/plugins/blog/api/serializers.mjs +18 -0
  23. package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.cjs +15 -2
  24. package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.mjs +16 -3
  25. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.cjs +24 -1
  26. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.mjs +24 -1
  27. package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.cjs +26 -0
  28. package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.mjs +24 -0
  29. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.cjs +30 -1
  30. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.mjs +30 -1
  31. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +18 -0
  32. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +18 -0
  33. package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +15 -0
  34. package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +16 -1
  35. package/dist/packages/stack/src/plugins/cms/api/getters.cjs +10 -0
  36. package/dist/packages/stack/src/plugins/cms/api/getters.mjs +10 -1
  37. package/dist/packages/stack/src/plugins/cms/api/mutations.cjs +48 -0
  38. package/dist/packages/stack/src/plugins/cms/api/mutations.mjs +46 -0
  39. package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +75 -0
  40. package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +76 -1
  41. package/dist/packages/stack/src/plugins/cms/api/query-key-defs.cjs +29 -0
  42. package/dist/packages/stack/src/plugins/cms/api/query-key-defs.mjs +26 -0
  43. package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +15 -0
  44. package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +16 -1
  45. package/dist/packages/stack/src/plugins/form-builder/api/getters.cjs +9 -0
  46. package/dist/packages/stack/src/plugins/form-builder/api/getters.mjs +9 -1
  47. package/dist/packages/stack/src/plugins/form-builder/api/plugin.cjs +62 -1
  48. package/dist/packages/stack/src/plugins/form-builder/api/plugin.mjs +63 -2
  49. package/dist/packages/stack/src/plugins/form-builder/api/query-key-defs.cjs +37 -0
  50. package/dist/packages/stack/src/plugins/form-builder/api/query-key-defs.mjs +33 -0
  51. package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +15 -0
  52. package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +16 -1
  53. package/dist/packages/stack/src/plugins/kanban/api/mutations.cjs +91 -0
  54. package/dist/packages/stack/src/plugins/kanban/api/mutations.mjs +87 -0
  55. package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +34 -1
  56. package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +34 -1
  57. package/dist/packages/stack/src/plugins/kanban/api/query-key-defs.cjs +26 -0
  58. package/dist/packages/stack/src/plugins/kanban/api/query-key-defs.mjs +23 -0
  59. package/dist/packages/stack/src/plugins/kanban/api/serializers.cjs +30 -0
  60. package/dist/packages/stack/src/plugins/kanban/api/serializers.mjs +26 -0
  61. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.cjs +7 -3
  62. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.mjs +7 -3
  63. package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +10 -0
  64. package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +11 -1
  65. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.cjs +89 -0
  66. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.mjs +89 -0
  67. package/dist/packages/stack/src/plugins/utils.cjs +6 -0
  68. package/dist/packages/stack/src/plugins/utils.mjs +6 -1
  69. package/dist/plugins/ai-chat/api/index.d.cts +1 -1
  70. package/dist/plugins/ai-chat/api/index.d.mts +1 -1
  71. package/dist/plugins/ai-chat/api/index.d.ts +1 -1
  72. package/dist/plugins/ai-chat/client/components/index.d.cts +1 -1
  73. package/dist/plugins/ai-chat/client/components/index.d.mts +1 -1
  74. package/dist/plugins/ai-chat/client/components/index.d.ts +1 -1
  75. package/dist/plugins/ai-chat/client/context/page-ai-context.cjs +92 -0
  76. package/dist/plugins/ai-chat/client/context/page-ai-context.d.cts +84 -0
  77. package/dist/plugins/ai-chat/client/context/page-ai-context.d.mts +84 -0
  78. package/dist/plugins/ai-chat/client/context/page-ai-context.d.ts +84 -0
  79. package/dist/plugins/ai-chat/client/context/page-ai-context.mjs +88 -0
  80. package/dist/plugins/ai-chat/client/hooks/index.d.cts +1 -1
  81. package/dist/plugins/ai-chat/client/hooks/index.d.mts +1 -1
  82. package/dist/plugins/ai-chat/client/hooks/index.d.ts +1 -1
  83. package/dist/plugins/ai-chat/client/index.d.cts +2 -2
  84. package/dist/plugins/ai-chat/client/index.d.mts +2 -2
  85. package/dist/plugins/ai-chat/client/index.d.ts +2 -2
  86. package/dist/plugins/ai-chat/query-keys.d.cts +1 -1
  87. package/dist/plugins/ai-chat/query-keys.d.mts +1 -1
  88. package/dist/plugins/ai-chat/query-keys.d.ts +1 -1
  89. package/dist/plugins/blog/api/index.cjs +5 -0
  90. package/dist/plugins/blog/api/index.d.cts +19 -4
  91. package/dist/plugins/blog/api/index.d.mts +19 -4
  92. package/dist/plugins/blog/api/index.d.ts +19 -4
  93. package/dist/plugins/blog/api/index.mjs +2 -0
  94. package/dist/plugins/blog/client/hooks/index.d.cts +3 -3
  95. package/dist/plugins/blog/client/hooks/index.d.mts +3 -3
  96. package/dist/plugins/blog/client/hooks/index.d.ts +3 -3
  97. package/dist/plugins/blog/client/index.d.cts +1 -1
  98. package/dist/plugins/blog/client/index.d.mts +1 -1
  99. package/dist/plugins/blog/client/index.d.ts +1 -1
  100. package/dist/plugins/blog/query-keys.cjs +6 -5
  101. package/dist/plugins/blog/query-keys.d.cts +8 -387
  102. package/dist/plugins/blog/query-keys.d.mts +8 -387
  103. package/dist/plugins/blog/query-keys.d.ts +8 -387
  104. package/dist/plugins/blog/query-keys.mjs +6 -5
  105. package/dist/plugins/client/index.cjs +1 -0
  106. package/dist/plugins/client/index.d.cts +8 -1
  107. package/dist/plugins/client/index.d.mts +8 -1
  108. package/dist/plugins/client/index.d.ts +8 -1
  109. package/dist/plugins/client/index.mjs +1 -1
  110. package/dist/plugins/cms/api/index.cjs +8 -0
  111. package/dist/plugins/cms/api/index.d.cts +7 -219
  112. package/dist/plugins/cms/api/index.d.mts +7 -219
  113. package/dist/plugins/cms/api/index.d.ts +7 -219
  114. package/dist/plugins/cms/api/index.mjs +3 -1
  115. package/dist/plugins/cms/client/hooks/index.d.cts +1 -1
  116. package/dist/plugins/cms/client/hooks/index.d.mts +1 -1
  117. package/dist/plugins/cms/client/hooks/index.d.ts +1 -1
  118. package/dist/plugins/cms/query-keys.cjs +2 -1
  119. package/dist/plugins/cms/query-keys.d.cts +5 -9
  120. package/dist/plugins/cms/query-keys.d.mts +5 -9
  121. package/dist/plugins/cms/query-keys.d.ts +5 -9
  122. package/dist/plugins/cms/query-keys.mjs +2 -1
  123. package/dist/plugins/form-builder/api/index.cjs +6 -0
  124. package/dist/plugins/form-builder/api/index.d.cts +7 -211
  125. package/dist/plugins/form-builder/api/index.d.mts +7 -211
  126. package/dist/plugins/form-builder/api/index.d.ts +7 -211
  127. package/dist/plugins/form-builder/api/index.mjs +2 -1
  128. package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
  129. package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
  130. package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
  131. package/dist/plugins/form-builder/client/hooks/index.d.cts +1 -1
  132. package/dist/plugins/form-builder/client/hooks/index.d.mts +1 -1
  133. package/dist/plugins/form-builder/client/hooks/index.d.ts +1 -1
  134. package/dist/plugins/form-builder/query-keys.cjs +3 -2
  135. package/dist/plugins/form-builder/query-keys.d.cts +6 -6
  136. package/dist/plugins/form-builder/query-keys.d.mts +6 -6
  137. package/dist/plugins/form-builder/query-keys.d.ts +6 -6
  138. package/dist/plugins/form-builder/query-keys.mjs +3 -2
  139. package/dist/plugins/kanban/api/index.cjs +10 -0
  140. package/dist/plugins/kanban/api/index.d.cts +17 -392
  141. package/dist/plugins/kanban/api/index.d.mts +17 -392
  142. package/dist/plugins/kanban/api/index.d.ts +17 -392
  143. package/dist/plugins/kanban/api/index.mjs +3 -0
  144. package/dist/plugins/kanban/client/components/index.d.cts +1 -1
  145. package/dist/plugins/kanban/client/components/index.d.mts +1 -1
  146. package/dist/plugins/kanban/client/components/index.d.ts +1 -1
  147. package/dist/plugins/kanban/client/hooks/index.d.cts +1 -1
  148. package/dist/plugins/kanban/client/hooks/index.d.mts +1 -1
  149. package/dist/plugins/kanban/client/hooks/index.d.ts +1 -1
  150. package/dist/plugins/kanban/client/index.d.cts +1 -1
  151. package/dist/plugins/kanban/client/index.d.mts +1 -1
  152. package/dist/plugins/kanban/client/index.d.ts +1 -1
  153. package/dist/plugins/kanban/query-keys.cjs +2 -9
  154. package/dist/plugins/kanban/query-keys.d.cts +4 -16
  155. package/dist/plugins/kanban/query-keys.d.mts +4 -16
  156. package/dist/plugins/kanban/query-keys.d.ts +4 -16
  157. package/dist/plugins/kanban/query-keys.mjs +2 -9
  158. package/dist/plugins/ui-builder/index.d.cts +1 -1
  159. package/dist/plugins/ui-builder/index.d.mts +1 -1
  160. package/dist/plugins/ui-builder/index.d.ts +1 -1
  161. package/dist/shared/stack.B7ONvlD_.d.mts +293 -0
  162. package/dist/shared/{stack.BeSm90va.d.ts → stack.BEn34wW6.d.ts} +60 -2
  163. package/dist/shared/stack.BUkC2EsZ.d.cts +327 -0
  164. package/dist/shared/{stack.DaOcgmrM.d.ts → stack.BV9hnvu4.d.cts} +31 -7
  165. package/dist/shared/{stack.DaOcgmrM.d.cts → stack.BV9hnvu4.d.mts} +31 -7
  166. package/dist/shared/{stack.DaOcgmrM.d.mts → stack.BV9hnvu4.d.ts} +31 -7
  167. package/dist/shared/stack.BepFXT3w.d.mts +500 -0
  168. package/dist/shared/stack.CL8ts1Mu.d.ts +419 -0
  169. package/dist/shared/{stack.CXjzTMsb.d.cts → stack.CVDTkMoO.d.cts} +7 -1
  170. package/dist/shared/{stack.CXjzTMsb.d.mts → stack.CVDTkMoO.d.mts} +7 -1
  171. package/dist/shared/{stack.CXjzTMsb.d.ts → stack.CVDTkMoO.d.ts} +7 -1
  172. package/dist/shared/stack.CczspVn2.d.mts +327 -0
  173. package/dist/shared/stack.CgWzG5jH.d.ts +500 -0
  174. package/dist/shared/stack.D3GB6wKv.d.cts +500 -0
  175. package/dist/shared/stack.DASmUVjX.d.ts +327 -0
  176. package/dist/shared/{stack.QD1y_7NY.d.cts → stack.DJaKVY7v.d.cts} +1 -1
  177. package/dist/shared/{stack.QD1y_7NY.d.mts → stack.DJaKVY7v.d.mts} +1 -1
  178. package/dist/shared/{stack.QD1y_7NY.d.ts → stack.DJaKVY7v.d.ts} +1 -1
  179. package/dist/shared/{stack.Dg09R0oB.d.mts → stack.DTDxgFj8.d.mts} +60 -2
  180. package/dist/shared/{stack.CMh_EdxW.d.cts → stack.DWoCZff7.d.cts} +60 -2
  181. package/dist/shared/{stack.CIrIsc-A.d.cts → stack.DdI5W6MB.d.cts} +7 -1
  182. package/dist/shared/{stack.CIrIsc-A.d.mts → stack.DdI5W6MB.d.mts} +7 -1
  183. package/dist/shared/{stack.CIrIsc-A.d.ts → stack.DdI5W6MB.d.ts} +7 -1
  184. package/dist/shared/stack.Dk5r4W1F.d.mts +419 -0
  185. package/dist/shared/stack.Kq2-QzOC.d.ts +293 -0
  186. package/dist/shared/stack.heOA9gzA.d.cts +419 -0
  187. package/dist/shared/stack.kcdnD4gA.d.cts +293 -0
  188. package/package.json +16 -3
  189. package/src/client/components/compose.tsx +7 -4
  190. package/src/plugins/ai-chat/api/page-tools.ts +111 -0
  191. package/src/plugins/ai-chat/api/plugin.ts +180 -9
  192. package/src/plugins/ai-chat/client/components/chat-input.tsx +2 -2
  193. package/src/plugins/ai-chat/client/components/chat-interface.tsx +154 -58
  194. package/src/plugins/ai-chat/client/components/chat-layout.tsx +166 -32
  195. package/src/plugins/ai-chat/client/components/chat-sidebar.tsx +1 -1
  196. package/src/plugins/ai-chat/client/context/page-ai-context.tsx +240 -0
  197. package/src/plugins/ai-chat/schemas.ts +16 -0
  198. package/src/plugins/blog/api/index.ts +2 -0
  199. package/src/plugins/blog/api/plugin.ts +85 -0
  200. package/src/plugins/blog/api/query-key-defs.ts +46 -0
  201. package/src/plugins/blog/api/serializers.ts +27 -0
  202. package/src/plugins/blog/client/components/forms/post-forms.tsx +29 -2
  203. package/src/plugins/blog/client/components/pages/edit-post-page.internal.tsx +28 -0
  204. package/src/plugins/blog/client/components/pages/fill-blog-form-handler.ts +38 -0
  205. package/src/plugins/blog/client/components/pages/new-post-page.internal.tsx +33 -1
  206. package/src/plugins/blog/client/components/pages/post-page.internal.tsx +20 -0
  207. package/src/plugins/blog/client/plugin.tsx +19 -0
  208. package/src/plugins/blog/query-keys.ts +5 -7
  209. package/src/plugins/client/index.ts +1 -1
  210. package/src/plugins/cms/api/getters.ts +24 -0
  211. package/src/plugins/cms/api/index.ts +14 -1
  212. package/src/plugins/cms/api/mutations.ts +84 -0
  213. package/src/plugins/cms/api/plugin.ts +114 -0
  214. package/src/plugins/cms/api/query-key-defs.ts +53 -0
  215. package/src/plugins/cms/api/serializers.ts +12 -0
  216. package/src/plugins/cms/client/plugin.tsx +19 -0
  217. package/src/plugins/cms/query-keys.ts +2 -1
  218. package/src/plugins/form-builder/api/getters.ts +23 -0
  219. package/src/plugins/form-builder/api/index.ts +15 -2
  220. package/src/plugins/form-builder/api/plugin.ts +91 -0
  221. package/src/plugins/form-builder/api/query-key-defs.ts +79 -0
  222. package/src/plugins/form-builder/api/serializers.ts +12 -0
  223. package/src/plugins/form-builder/client/plugin.tsx +19 -0
  224. package/src/plugins/form-builder/query-keys.ts +6 -2
  225. package/src/plugins/kanban/api/index.ts +9 -0
  226. package/src/plugins/kanban/api/mutations.ts +169 -0
  227. package/src/plugins/kanban/api/plugin.ts +61 -0
  228. package/src/plugins/kanban/api/query-key-defs.ts +54 -0
  229. package/src/plugins/kanban/api/serializers.ts +49 -0
  230. package/src/plugins/kanban/client/hooks/kanban-hooks.tsx +4 -0
  231. package/src/plugins/kanban/client/plugin.tsx +13 -0
  232. package/src/plugins/kanban/query-keys.ts +2 -9
  233. package/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.tsx +132 -0
  234. package/src/plugins/utils.ts +19 -0
  235. package/dist/shared/{stack.BkYlUT_8.d.cts → stack.BQmuNl5p.d.cts} +6 -6
  236. package/dist/shared/{stack.BkYlUT_8.d.mts → stack.BQmuNl5p.d.mts} +6 -6
  237. package/dist/shared/{stack.BkYlUT_8.d.ts → stack.BQmuNl5p.d.ts} +6 -6
@@ -4,15 +4,76 @@ import { formSchemaToZod } from '../../../../../ui/src/lib/schema-converter.mjs'
4
4
  import { formBuilderSchema } from '../db.mjs';
5
5
  import { listFormsQuerySchema, createFormSchema, updateFormSchema, listSubmissionsQuerySchema } from '../schemas.mjs';
6
6
  import { extractUserAgent, extractIpAddress, slugify } from '../utils.mjs';
7
- import { getFormSubmissions, getFormBySlug, getAllForms, serializeForm, serializeFormSubmission, serializeFormSubmissionWithData } from './getters.mjs';
7
+ import { getFormSubmissions, getFormBySlug, getFormById, getAllForms, serializeForm, serializeFormSubmission, serializeFormSubmissionWithData } from './getters.mjs';
8
+ import { FORM_QUERY_KEYS } from './query-key-defs.mjs';
8
9
 
10
+ function createFormBuilderPrefetchForRoute(adapter) {
11
+ return async function prefetchForRoute(key, qc, params) {
12
+ switch (key) {
13
+ case "formList": {
14
+ const result = await getAllForms(adapter, { limit: 20, offset: 0 });
15
+ qc.setQueryData(FORM_QUERY_KEYS.formsList({ limit: 20, offset: 0 }), {
16
+ pages: [
17
+ {
18
+ items: result.items,
19
+ total: result.total,
20
+ limit: result.limit ?? 20,
21
+ offset: result.offset ?? 0
22
+ }
23
+ ],
24
+ pageParams: [0]
25
+ });
26
+ break;
27
+ }
28
+ case "editForm": {
29
+ const id = params?.id ?? "";
30
+ if (id) {
31
+ const form = await getFormById(adapter, id);
32
+ qc.setQueryData(FORM_QUERY_KEYS.formById(id), form);
33
+ }
34
+ break;
35
+ }
36
+ case "submissions": {
37
+ const id = params?.id ?? "";
38
+ if (id) {
39
+ const [form, submissionsResult] = await Promise.all([
40
+ getFormById(adapter, id),
41
+ getFormSubmissions(adapter, id, { limit: 20, offset: 0 })
42
+ ]);
43
+ qc.setQueryData(FORM_QUERY_KEYS.formById(id), form);
44
+ qc.setQueryData(
45
+ FORM_QUERY_KEYS.submissionsList({
46
+ formId: id,
47
+ limit: 20,
48
+ offset: 0
49
+ }),
50
+ {
51
+ pages: [
52
+ {
53
+ items: submissionsResult.items,
54
+ total: submissionsResult.total,
55
+ limit: submissionsResult.limit ?? 20,
56
+ offset: submissionsResult.offset ?? 0
57
+ }
58
+ ],
59
+ pageParams: [0]
60
+ }
61
+ );
62
+ }
63
+ break;
64
+ }
65
+ }
66
+ };
67
+ }
9
68
  const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
10
69
  name: "form-builder",
11
70
  dbPlugin: formBuilderSchema,
12
71
  api: (adapter) => ({
13
72
  getAllForms: (params) => getAllForms(adapter, params),
73
+ getFormById: (id) => getFormById(adapter, id),
14
74
  getFormBySlug: (slug) => getFormBySlug(adapter, slug),
15
- getFormSubmissions: (formId, params) => getFormSubmissions(adapter, formId, params)
75
+ getFormSubmissions: (formId, params) => getFormSubmissions(adapter, formId, params),
76
+ prefetchForRoute: createFormBuilderPrefetchForRoute(adapter)
16
77
  }),
17
78
  routes: (adapter) => {
18
79
  const createContext = (headers) => ({
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ function formsListDiscriminator(params) {
4
+ return {
5
+ status: params?.status,
6
+ limit: params?.limit ?? 20,
7
+ offset: params?.offset ?? 0
8
+ };
9
+ }
10
+ function submissionsListDiscriminator(params) {
11
+ return {
12
+ formId: params.formId,
13
+ limit: params.limit ?? 20,
14
+ offset: params.offset ?? 0
15
+ };
16
+ }
17
+ const FORM_QUERY_KEYS = {
18
+ /**
19
+ * Key for forms.list(params) query.
20
+ * Full key: ["forms", "list", "list", { status, limit, offset }]
21
+ */
22
+ formsList: (params) => ["forms", "list", "list", formsListDiscriminator(params)],
23
+ /**
24
+ * Key for forms.byId(id) query.
25
+ * Full key: ["forms", "byId", "byId", id]
26
+ */
27
+ formById: (id) => ["forms", "byId", "byId", id],
28
+ /**
29
+ * Key for formSubmissions.list(params) query.
30
+ * Full key: ["formSubmissions", "list", { formId, limit, offset }]
31
+ */
32
+ submissionsList: (params) => ["formSubmissions", "list", submissionsListDiscriminator(params)]
33
+ };
34
+
35
+ exports.FORM_QUERY_KEYS = FORM_QUERY_KEYS;
36
+ exports.formsListDiscriminator = formsListDiscriminator;
37
+ exports.submissionsListDiscriminator = submissionsListDiscriminator;
@@ -0,0 +1,33 @@
1
+ function formsListDiscriminator(params) {
2
+ return {
3
+ status: params?.status,
4
+ limit: params?.limit ?? 20,
5
+ offset: params?.offset ?? 0
6
+ };
7
+ }
8
+ function submissionsListDiscriminator(params) {
9
+ return {
10
+ formId: params.formId,
11
+ limit: params.limit ?? 20,
12
+ offset: params.offset ?? 0
13
+ };
14
+ }
15
+ const FORM_QUERY_KEYS = {
16
+ /**
17
+ * Key for forms.list(params) query.
18
+ * Full key: ["forms", "list", "list", { status, limit, offset }]
19
+ */
20
+ formsList: (params) => ["forms", "list", "list", formsListDiscriminator(params)],
21
+ /**
22
+ * Key for forms.byId(id) query.
23
+ * Full key: ["forms", "byId", "byId", id]
24
+ */
25
+ formById: (id) => ["forms", "byId", "byId", id],
26
+ /**
27
+ * Key for formSubmissions.list(params) query.
28
+ * Full key: ["formSubmissions", "list", { formId, limit, offset }]
29
+ */
30
+ submissionsList: (params) => ["formSubmissions", "list", submissionsListDiscriminator(params)]
31
+ };
32
+
33
+ export { FORM_QUERY_KEYS, formsListDiscriminator, submissionsListDiscriminator };
@@ -70,6 +70,11 @@ function createFormListLoader(config) {
70
70
  await hooks.onLoadError(error, context);
71
71
  }
72
72
  } catch (error) {
73
+ if (client.isConnectionError(error)) {
74
+ console.warn(
75
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
76
+ );
77
+ }
73
78
  if (hooks?.onLoadError) {
74
79
  await hooks.onLoadError(error, context);
75
80
  }
@@ -117,6 +122,11 @@ function createFormBuilderLoader(id, config) {
117
122
  }
118
123
  }
119
124
  } catch (error) {
125
+ if (client.isConnectionError(error)) {
126
+ console.warn(
127
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
128
+ );
129
+ }
120
130
  if (hooks?.onLoadError) {
121
131
  await hooks.onLoadError(error, context);
122
132
  }
@@ -189,6 +199,11 @@ function createSubmissionsLoader(formId, config) {
189
199
  await hooks.onLoadError(error, context);
190
200
  }
191
201
  } catch (error) {
202
+ if (client.isConnectionError(error)) {
203
+ console.warn(
204
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
205
+ );
206
+ }
192
207
  if (hooks?.onLoadError) {
193
208
  await hooks.onLoadError(error, context);
194
209
  }
@@ -1,6 +1,6 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { lazy } from 'react';
3
- import { defineClientPlugin, createApiClient } from '@btst/stack/plugins/client';
3
+ import { defineClientPlugin, createApiClient, isConnectionError } from '@btst/stack/plugins/client';
4
4
  import { createRoute } from '@btst/yar';
5
5
  import { createFormBuilderQueryKeys } from '../../../../../../plugins/form-builder/query-keys.mjs';
6
6
 
@@ -68,6 +68,11 @@ function createFormListLoader(config) {
68
68
  await hooks.onLoadError(error, context);
69
69
  }
70
70
  } catch (error) {
71
+ if (isConnectionError(error)) {
72
+ console.warn(
73
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
74
+ );
75
+ }
71
76
  if (hooks?.onLoadError) {
72
77
  await hooks.onLoadError(error, context);
73
78
  }
@@ -115,6 +120,11 @@ function createFormBuilderLoader(id, config) {
115
120
  }
116
121
  }
117
122
  } catch (error) {
123
+ if (isConnectionError(error)) {
124
+ console.warn(
125
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
126
+ );
127
+ }
118
128
  if (hooks?.onLoadError) {
119
129
  await hooks.onLoadError(error, context);
120
130
  }
@@ -187,6 +197,11 @@ function createSubmissionsLoader(formId, config) {
187
197
  await hooks.onLoadError(error, context);
188
198
  }
189
199
  } catch (error) {
200
+ if (isConnectionError(error)) {
201
+ console.warn(
202
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
203
+ );
204
+ }
190
205
  if (hooks?.onLoadError) {
191
206
  await hooks.onLoadError(error, context);
192
207
  }
@@ -0,0 +1,91 @@
1
+ 'use strict';
2
+
3
+ async function createKanbanTask(adapter, input) {
4
+ const existingTasks = await adapter.findMany({
5
+ model: "kanbanTask",
6
+ where: [
7
+ {
8
+ field: "columnId",
9
+ value: input.columnId,
10
+ operator: "eq"
11
+ }
12
+ ]
13
+ });
14
+ const nextOrder = existingTasks.length > 0 ? Math.max(...existingTasks.map((t) => t.order)) + 1 : 0;
15
+ return adapter.create({
16
+ model: "kanbanTask",
17
+ data: {
18
+ title: input.title,
19
+ columnId: input.columnId,
20
+ description: input.description,
21
+ priority: input.priority ?? "MEDIUM",
22
+ order: nextOrder,
23
+ assigneeId: input.assigneeId,
24
+ isArchived: false,
25
+ createdAt: /* @__PURE__ */ new Date(),
26
+ updatedAt: /* @__PURE__ */ new Date()
27
+ }
28
+ });
29
+ }
30
+ const _pendingBoardCreations = /* @__PURE__ */ new Map();
31
+ async function findOrCreateKanbanBoard(adapter, slug, name, columnTitles) {
32
+ const existing = await adapter.findOne({
33
+ model: "kanbanBoard",
34
+ where: [{ field: "slug", value: slug, operator: "eq" }]
35
+ });
36
+ if (existing) return existing;
37
+ const inflight = _pendingBoardCreations.get(slug);
38
+ if (inflight) return inflight;
39
+ const creation = (async () => {
40
+ try {
41
+ const board = await adapter.create({
42
+ model: "kanbanBoard",
43
+ data: {
44
+ name,
45
+ slug,
46
+ createdAt: /* @__PURE__ */ new Date(),
47
+ updatedAt: /* @__PURE__ */ new Date()
48
+ }
49
+ });
50
+ await Promise.all(
51
+ columnTitles.map(
52
+ (title, index) => adapter.create({
53
+ model: "kanbanColumn",
54
+ data: {
55
+ title,
56
+ boardId: board.id,
57
+ order: index,
58
+ createdAt: /* @__PURE__ */ new Date(),
59
+ updatedAt: /* @__PURE__ */ new Date()
60
+ }
61
+ })
62
+ )
63
+ );
64
+ return board;
65
+ } catch (err) {
66
+ const winner = await adapter.findOne({
67
+ model: "kanbanBoard",
68
+ where: [{ field: "slug", value: slug, operator: "eq" }]
69
+ });
70
+ if (winner) return winner;
71
+ throw err;
72
+ }
73
+ })();
74
+ _pendingBoardCreations.set(slug, creation);
75
+ try {
76
+ return await creation;
77
+ } finally {
78
+ _pendingBoardCreations.delete(slug);
79
+ }
80
+ }
81
+ async function getKanbanColumnsByBoardId(adapter, boardId) {
82
+ return adapter.findMany({
83
+ model: "kanbanColumn",
84
+ where: [{ field: "boardId", value: boardId, operator: "eq" }],
85
+ sortBy: { field: "order", direction: "asc" }
86
+ });
87
+ }
88
+
89
+ exports.createKanbanTask = createKanbanTask;
90
+ exports.findOrCreateKanbanBoard = findOrCreateKanbanBoard;
91
+ exports.getKanbanColumnsByBoardId = getKanbanColumnsByBoardId;
@@ -0,0 +1,87 @@
1
+ async function createKanbanTask(adapter, input) {
2
+ const existingTasks = await adapter.findMany({
3
+ model: "kanbanTask",
4
+ where: [
5
+ {
6
+ field: "columnId",
7
+ value: input.columnId,
8
+ operator: "eq"
9
+ }
10
+ ]
11
+ });
12
+ const nextOrder = existingTasks.length > 0 ? Math.max(...existingTasks.map((t) => t.order)) + 1 : 0;
13
+ return adapter.create({
14
+ model: "kanbanTask",
15
+ data: {
16
+ title: input.title,
17
+ columnId: input.columnId,
18
+ description: input.description,
19
+ priority: input.priority ?? "MEDIUM",
20
+ order: nextOrder,
21
+ assigneeId: input.assigneeId,
22
+ isArchived: false,
23
+ createdAt: /* @__PURE__ */ new Date(),
24
+ updatedAt: /* @__PURE__ */ new Date()
25
+ }
26
+ });
27
+ }
28
+ const _pendingBoardCreations = /* @__PURE__ */ new Map();
29
+ async function findOrCreateKanbanBoard(adapter, slug, name, columnTitles) {
30
+ const existing = await adapter.findOne({
31
+ model: "kanbanBoard",
32
+ where: [{ field: "slug", value: slug, operator: "eq" }]
33
+ });
34
+ if (existing) return existing;
35
+ const inflight = _pendingBoardCreations.get(slug);
36
+ if (inflight) return inflight;
37
+ const creation = (async () => {
38
+ try {
39
+ const board = await adapter.create({
40
+ model: "kanbanBoard",
41
+ data: {
42
+ name,
43
+ slug,
44
+ createdAt: /* @__PURE__ */ new Date(),
45
+ updatedAt: /* @__PURE__ */ new Date()
46
+ }
47
+ });
48
+ await Promise.all(
49
+ columnTitles.map(
50
+ (title, index) => adapter.create({
51
+ model: "kanbanColumn",
52
+ data: {
53
+ title,
54
+ boardId: board.id,
55
+ order: index,
56
+ createdAt: /* @__PURE__ */ new Date(),
57
+ updatedAt: /* @__PURE__ */ new Date()
58
+ }
59
+ })
60
+ )
61
+ );
62
+ return board;
63
+ } catch (err) {
64
+ const winner = await adapter.findOne({
65
+ model: "kanbanBoard",
66
+ where: [{ field: "slug", value: slug, operator: "eq" }]
67
+ });
68
+ if (winner) return winner;
69
+ throw err;
70
+ }
71
+ })();
72
+ _pendingBoardCreations.set(slug, creation);
73
+ try {
74
+ return await creation;
75
+ } finally {
76
+ _pendingBoardCreations.delete(slug);
77
+ }
78
+ }
79
+ async function getKanbanColumnsByBoardId(adapter, boardId) {
80
+ return adapter.findMany({
81
+ model: "kanbanColumn",
82
+ where: [{ field: "boardId", value: boardId, operator: "eq" }],
83
+ sortBy: { field: "order", direction: "asc" }
84
+ });
85
+ }
86
+
87
+ export { createKanbanTask, findOrCreateKanbanBoard, getKanbanColumnsByBoardId };
@@ -5,13 +5,46 @@ const db = require('../db.cjs');
5
5
  const utils = require('../utils.cjs');
6
6
  const schemas = require('../schemas.cjs');
7
7
  const getters = require('./getters.cjs');
8
+ const mutations = require('./mutations.cjs');
9
+ const queryKeyDefs = require('./query-key-defs.cjs');
10
+ const serializers = require('./serializers.cjs');
8
11
 
12
+ function createKanbanPrefetchForRoute(adapter) {
13
+ return async function prefetchForRoute(key, qc, params) {
14
+ switch (key) {
15
+ case "boards": {
16
+ const result = await getters.getAllBoards(adapter, { limit: 50, offset: 0 });
17
+ qc.setQueryData(
18
+ queryKeyDefs.KANBAN_QUERY_KEYS.boardsList({}),
19
+ result.items.map(serializers.serializeBoard)
20
+ );
21
+ break;
22
+ }
23
+ case "board": {
24
+ const boardId = params?.boardId ?? "";
25
+ if (boardId) {
26
+ const board = await getters.getBoardById(adapter, boardId);
27
+ qc.setQueryData(
28
+ queryKeyDefs.KANBAN_QUERY_KEYS.boardDetail(boardId),
29
+ board ? serializers.serializeBoard(board) : null
30
+ );
31
+ }
32
+ break;
33
+ }
34
+ }
35
+ };
36
+ }
9
37
  const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
10
38
  name: "kanban",
11
39
  dbPlugin: db.kanbanSchema,
12
40
  api: (adapter) => ({
13
41
  getAllBoards: (params) => getters.getAllBoards(adapter, params),
14
- getBoardById: (id) => getters.getBoardById(adapter, id)
42
+ getBoardById: (id) => getters.getBoardById(adapter, id),
43
+ prefetchForRoute: createKanbanPrefetchForRoute(adapter),
44
+ // Mutations
45
+ createTask: (input) => mutations.createKanbanTask(adapter, input),
46
+ findOrCreateBoard: (slug, name, columnTitles) => mutations.findOrCreateKanbanBoard(adapter, slug, name, columnTitles),
47
+ getColumnsByBoardId: (boardId) => mutations.getKanbanColumnsByBoardId(adapter, boardId)
15
48
  }),
16
49
  routes: (adapter) => {
17
50
  const listBoards = api.createEndpoint(
@@ -3,13 +3,46 @@ import { kanbanSchema } from '../db.mjs';
3
3
  import { slugify } from '../utils.mjs';
4
4
  import { BoardListQuerySchema, createBoardSchema, updateBoardSchema, createColumnSchema, updateColumnSchema, reorderColumnsSchema, createTaskSchema, updateTaskSchema, moveTaskSchema, reorderTasksSchema } from '../schemas.mjs';
5
5
  import { getBoardById, getAllBoards } from './getters.mjs';
6
+ import { getKanbanColumnsByBoardId, findOrCreateKanbanBoard, createKanbanTask } from './mutations.mjs';
7
+ import { KANBAN_QUERY_KEYS } from './query-key-defs.mjs';
8
+ import { serializeBoard } from './serializers.mjs';
6
9
 
10
+ function createKanbanPrefetchForRoute(adapter) {
11
+ return async function prefetchForRoute(key, qc, params) {
12
+ switch (key) {
13
+ case "boards": {
14
+ const result = await getAllBoards(adapter, { limit: 50, offset: 0 });
15
+ qc.setQueryData(
16
+ KANBAN_QUERY_KEYS.boardsList({}),
17
+ result.items.map(serializeBoard)
18
+ );
19
+ break;
20
+ }
21
+ case "board": {
22
+ const boardId = params?.boardId ?? "";
23
+ if (boardId) {
24
+ const board = await getBoardById(adapter, boardId);
25
+ qc.setQueryData(
26
+ KANBAN_QUERY_KEYS.boardDetail(boardId),
27
+ board ? serializeBoard(board) : null
28
+ );
29
+ }
30
+ break;
31
+ }
32
+ }
33
+ };
34
+ }
7
35
  const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
8
36
  name: "kanban",
9
37
  dbPlugin: kanbanSchema,
10
38
  api: (adapter) => ({
11
39
  getAllBoards: (params) => getAllBoards(adapter, params),
12
- getBoardById: (id) => getBoardById(adapter, id)
40
+ getBoardById: (id) => getBoardById(adapter, id),
41
+ prefetchForRoute: createKanbanPrefetchForRoute(adapter),
42
+ // Mutations
43
+ createTask: (input) => createKanbanTask(adapter, input),
44
+ findOrCreateBoard: (slug, name, columnTitles) => findOrCreateKanbanBoard(adapter, slug, name, columnTitles),
45
+ getColumnsByBoardId: (boardId) => getKanbanColumnsByBoardId(adapter, boardId)
13
46
  }),
14
47
  routes: (adapter) => {
15
48
  const listBoards = createEndpoint(
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ function boardsListDiscriminator(params) {
4
+ return {
5
+ slug: params?.slug,
6
+ ownerId: params?.ownerId,
7
+ organizationId: params?.organizationId,
8
+ limit: params?.limit ?? 50,
9
+ offset: params?.offset ?? 0
10
+ };
11
+ }
12
+ const KANBAN_QUERY_KEYS = {
13
+ /**
14
+ * Key for boards.list(params) query.
15
+ * Full key: ["boards", "list", { slug, ownerId, organizationId, limit, offset }]
16
+ */
17
+ boardsList: (params) => ["boards", "list", boardsListDiscriminator(params)],
18
+ /**
19
+ * Key for boards.detail(boardId) query.
20
+ * Full key: ["boards", "detail", boardId]
21
+ */
22
+ boardDetail: (boardId) => ["boards", "detail", boardId]
23
+ };
24
+
25
+ exports.KANBAN_QUERY_KEYS = KANBAN_QUERY_KEYS;
26
+ exports.boardsListDiscriminator = boardsListDiscriminator;
@@ -0,0 +1,23 @@
1
+ function boardsListDiscriminator(params) {
2
+ return {
3
+ slug: params?.slug,
4
+ ownerId: params?.ownerId,
5
+ organizationId: params?.organizationId,
6
+ limit: params?.limit ?? 50,
7
+ offset: params?.offset ?? 0
8
+ };
9
+ }
10
+ const KANBAN_QUERY_KEYS = {
11
+ /**
12
+ * Key for boards.list(params) query.
13
+ * Full key: ["boards", "list", { slug, ownerId, organizationId, limit, offset }]
14
+ */
15
+ boardsList: (params) => ["boards", "list", boardsListDiscriminator(params)],
16
+ /**
17
+ * Key for boards.detail(boardId) query.
18
+ * Full key: ["boards", "detail", boardId]
19
+ */
20
+ boardDetail: (boardId) => ["boards", "detail", boardId]
21
+ };
22
+
23
+ export { KANBAN_QUERY_KEYS, boardsListDiscriminator };
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ function serializeTask(task) {
4
+ return {
5
+ ...task,
6
+ completedAt: task.completedAt?.toISOString(),
7
+ createdAt: task.createdAt.toISOString(),
8
+ updatedAt: task.updatedAt.toISOString()
9
+ };
10
+ }
11
+ function serializeColumn(col) {
12
+ return {
13
+ ...col,
14
+ createdAt: col.createdAt.toISOString(),
15
+ updatedAt: col.updatedAt.toISOString(),
16
+ tasks: col.tasks.map(serializeTask)
17
+ };
18
+ }
19
+ function serializeBoard(board) {
20
+ return {
21
+ ...board,
22
+ createdAt: board.createdAt.toISOString(),
23
+ updatedAt: board.updatedAt.toISOString(),
24
+ columns: board.columns.map(serializeColumn)
25
+ };
26
+ }
27
+
28
+ exports.serializeBoard = serializeBoard;
29
+ exports.serializeColumn = serializeColumn;
30
+ exports.serializeTask = serializeTask;
@@ -0,0 +1,26 @@
1
+ function serializeTask(task) {
2
+ return {
3
+ ...task,
4
+ completedAt: task.completedAt?.toISOString(),
5
+ createdAt: task.createdAt.toISOString(),
6
+ updatedAt: task.updatedAt.toISOString()
7
+ };
8
+ }
9
+ function serializeColumn(col) {
10
+ return {
11
+ ...col,
12
+ createdAt: col.createdAt.toISOString(),
13
+ updatedAt: col.updatedAt.toISOString(),
14
+ tasks: col.tasks.map(serializeTask)
15
+ };
16
+ }
17
+ function serializeBoard(board) {
18
+ return {
19
+ ...board,
20
+ createdAt: board.createdAt.toISOString(),
21
+ updatedAt: board.updatedAt.toISOString(),
22
+ columns: board.columns.map(serializeColumn)
23
+ };
24
+ }
25
+
26
+ export { serializeBoard, serializeColumn, serializeTask };
@@ -35,7 +35,8 @@ function useBoards(params) {
35
35
  const queries = plugins_kanban_queryKeys.createKanbanQueryKeys(client, headers);
36
36
  return reactQuery.useQuery({
37
37
  ...queries.boards.list(params),
38
- staleTime: 3e4
38
+ staleTime: 3e4,
39
+ refetchOnWindowFocus: true
39
40
  });
40
41
  }
41
42
  function useSuspenseBoards(params) {
@@ -43,7 +44,8 @@ function useSuspenseBoards(params) {
43
44
  const queries = plugins_kanban_queryKeys.createKanbanQueryKeys(client, headers);
44
45
  const result = reactQuery.useSuspenseQuery({
45
46
  ...queries.boards.list(params),
46
- staleTime: 3e4
47
+ staleTime: 3e4,
48
+ refetchOnWindowFocus: true
47
49
  });
48
50
  if (result.error && !result.isFetching) {
49
51
  throw result.error;
@@ -56,6 +58,7 @@ function useBoard(boardId) {
56
58
  return reactQuery.useQuery({
57
59
  ...queries.boards.detail(boardId),
58
60
  staleTime: 3e4,
61
+ refetchOnWindowFocus: true,
59
62
  enabled: !!boardId
60
63
  });
61
64
  }
@@ -64,7 +67,8 @@ function useSuspenseBoard(boardId) {
64
67
  const queries = plugins_kanban_queryKeys.createKanbanQueryKeys(client, headers);
65
68
  const result = reactQuery.useSuspenseQuery({
66
69
  ...queries.boards.detail(boardId),
67
- staleTime: 3e4
70
+ staleTime: 3e4,
71
+ refetchOnWindowFocus: true
68
72
  });
69
73
  if (result.error && !result.isFetching) {
70
74
  throw result.error;