@btst/stack 2.3.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/dist/packages/stack/src/client/components/compose.cjs +1 -2
  2. package/dist/packages/stack/src/client/components/compose.mjs +1 -2
  3. package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.cjs +71 -0
  4. package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.mjs +68 -0
  5. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.cjs +87 -54
  6. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +87 -54
  7. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.cjs +2 -2
  8. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.mjs +2 -2
  9. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.cjs +89 -22
  10. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.mjs +90 -23
  11. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.cjs +110 -33
  12. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.mjs +112 -35
  13. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.cjs +1 -1
  14. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.mjs +1 -1
  15. package/dist/packages/stack/src/plugins/ai-chat/client/plugin.cjs +14 -21
  16. package/dist/packages/stack/src/plugins/ai-chat/client/plugin.mjs +15 -22
  17. package/dist/packages/stack/src/plugins/ai-chat/schemas.cjs +17 -1
  18. package/dist/packages/stack/src/plugins/ai-chat/schemas.mjs +17 -1
  19. package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +28 -45
  20. package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +22 -39
  21. package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.cjs +15 -2
  22. package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.mjs +16 -3
  23. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.cjs +24 -1
  24. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.mjs +24 -1
  25. package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.cjs +26 -0
  26. package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.mjs +24 -0
  27. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.cjs +30 -1
  28. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.mjs +30 -1
  29. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +18 -0
  30. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +18 -0
  31. package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +23 -27
  32. package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +24 -28
  33. package/dist/packages/stack/src/plugins/cms/api/mutations.cjs +48 -0
  34. package/dist/packages/stack/src/plugins/cms/api/mutations.mjs +46 -0
  35. package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +21 -18
  36. package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +21 -18
  37. package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +11 -15
  38. package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +12 -16
  39. package/dist/packages/stack/src/plugins/form-builder/api/plugin.cjs +58 -62
  40. package/dist/packages/stack/src/plugins/form-builder/api/plugin.mjs +58 -62
  41. package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +12 -12
  42. package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +13 -13
  43. package/dist/packages/stack/src/plugins/kanban/api/mutations.cjs +91 -0
  44. package/dist/packages/stack/src/plugins/kanban/api/mutations.mjs +87 -0
  45. package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +92 -118
  46. package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +89 -115
  47. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.cjs +7 -3
  48. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.mjs +7 -3
  49. package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +22 -29
  50. package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +23 -30
  51. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.cjs +89 -0
  52. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.mjs +89 -0
  53. package/dist/packages/stack/src/plugins/ui-builder/client/plugin.cjs +8 -8
  54. package/dist/packages/stack/src/plugins/ui-builder/client/plugin.mjs +9 -9
  55. package/dist/packages/stack/src/plugins/utils.cjs +42 -0
  56. package/dist/packages/stack/src/plugins/utils.mjs +41 -1
  57. package/dist/plugins/ai-chat/api/index.d.cts +1 -1
  58. package/dist/plugins/ai-chat/api/index.d.mts +1 -1
  59. package/dist/plugins/ai-chat/api/index.d.ts +1 -1
  60. package/dist/plugins/ai-chat/client/components/index.d.cts +1 -1
  61. package/dist/plugins/ai-chat/client/components/index.d.mts +1 -1
  62. package/dist/plugins/ai-chat/client/components/index.d.ts +1 -1
  63. package/dist/plugins/ai-chat/client/context/page-ai-context.cjs +92 -0
  64. package/dist/plugins/ai-chat/client/context/page-ai-context.d.cts +84 -0
  65. package/dist/plugins/ai-chat/client/context/page-ai-context.d.mts +84 -0
  66. package/dist/plugins/ai-chat/client/context/page-ai-context.d.ts +84 -0
  67. package/dist/plugins/ai-chat/client/context/page-ai-context.mjs +88 -0
  68. package/dist/plugins/ai-chat/client/hooks/index.d.cts +1 -1
  69. package/dist/plugins/ai-chat/client/hooks/index.d.mts +1 -1
  70. package/dist/plugins/ai-chat/client/hooks/index.d.ts +1 -1
  71. package/dist/plugins/ai-chat/client/index.d.cts +10 -10
  72. package/dist/plugins/ai-chat/client/index.d.mts +10 -10
  73. package/dist/plugins/ai-chat/client/index.d.ts +10 -10
  74. package/dist/plugins/ai-chat/query-keys.d.cts +1 -1
  75. package/dist/plugins/ai-chat/query-keys.d.mts +1 -1
  76. package/dist/plugins/ai-chat/query-keys.d.ts +1 -1
  77. package/dist/plugins/blog/api/index.d.cts +2 -2
  78. package/dist/plugins/blog/api/index.d.mts +2 -2
  79. package/dist/plugins/blog/api/index.d.ts +2 -2
  80. package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
  81. package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
  82. package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
  83. package/dist/plugins/blog/client/index.d.cts +13 -13
  84. package/dist/plugins/blog/client/index.d.mts +13 -13
  85. package/dist/plugins/blog/client/index.d.ts +13 -13
  86. package/dist/plugins/blog/query-keys.d.cts +2 -2
  87. package/dist/plugins/blog/query-keys.d.mts +2 -2
  88. package/dist/plugins/blog/query-keys.d.ts +2 -2
  89. package/dist/plugins/client/index.cjs +1 -0
  90. package/dist/plugins/client/index.d.cts +8 -1
  91. package/dist/plugins/client/index.d.mts +8 -1
  92. package/dist/plugins/client/index.d.ts +8 -1
  93. package/dist/plugins/client/index.mjs +1 -1
  94. package/dist/plugins/cms/api/index.cjs +2 -0
  95. package/dist/plugins/cms/api/index.d.cts +2 -2
  96. package/dist/plugins/cms/api/index.d.mts +2 -2
  97. package/dist/plugins/cms/api/index.d.ts +2 -2
  98. package/dist/plugins/cms/api/index.mjs +1 -0
  99. package/dist/plugins/cms/client/hooks/index.d.cts +1 -1
  100. package/dist/plugins/cms/client/hooks/index.d.mts +1 -1
  101. package/dist/plugins/cms/client/hooks/index.d.ts +1 -1
  102. package/dist/plugins/cms/client/index.d.cts +6 -6
  103. package/dist/plugins/cms/client/index.d.mts +6 -6
  104. package/dist/plugins/cms/client/index.d.ts +6 -6
  105. package/dist/plugins/cms/query-keys.d.cts +2 -2
  106. package/dist/plugins/cms/query-keys.d.mts +2 -2
  107. package/dist/plugins/cms/query-keys.d.ts +2 -2
  108. package/dist/plugins/form-builder/api/index.d.cts +2 -2
  109. package/dist/plugins/form-builder/api/index.d.mts +2 -2
  110. package/dist/plugins/form-builder/api/index.d.ts +2 -2
  111. package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
  112. package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
  113. package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
  114. package/dist/plugins/form-builder/client/hooks/index.d.cts +1 -1
  115. package/dist/plugins/form-builder/client/hooks/index.d.mts +1 -1
  116. package/dist/plugins/form-builder/client/hooks/index.d.ts +1 -1
  117. package/dist/plugins/form-builder/client/index.d.cts +6 -6
  118. package/dist/plugins/form-builder/client/index.d.mts +6 -6
  119. package/dist/plugins/form-builder/client/index.d.ts +6 -6
  120. package/dist/plugins/form-builder/query-keys.d.cts +2 -2
  121. package/dist/plugins/form-builder/query-keys.d.mts +2 -2
  122. package/dist/plugins/form-builder/query-keys.d.ts +2 -2
  123. package/dist/plugins/kanban/api/index.cjs +4 -0
  124. package/dist/plugins/kanban/api/index.d.cts +1 -1
  125. package/dist/plugins/kanban/api/index.d.mts +1 -1
  126. package/dist/plugins/kanban/api/index.d.ts +1 -1
  127. package/dist/plugins/kanban/api/index.mjs +1 -0
  128. package/dist/plugins/kanban/client/index.d.cts +12 -12
  129. package/dist/plugins/kanban/client/index.d.mts +12 -12
  130. package/dist/plugins/kanban/client/index.d.ts +12 -12
  131. package/dist/plugins/kanban/query-keys.d.cts +1 -1
  132. package/dist/plugins/kanban/query-keys.d.mts +1 -1
  133. package/dist/plugins/kanban/query-keys.d.ts +1 -1
  134. package/dist/plugins/ui-builder/client/hooks/index.d.cts +1 -1
  135. package/dist/plugins/ui-builder/client/hooks/index.d.mts +1 -1
  136. package/dist/plugins/ui-builder/client/hooks/index.d.ts +1 -1
  137. package/dist/plugins/ui-builder/client/index.d.cts +3 -3
  138. package/dist/plugins/ui-builder/client/index.d.mts +3 -3
  139. package/dist/plugins/ui-builder/client/index.d.ts +3 -3
  140. package/dist/plugins/ui-builder/index.d.cts +2 -2
  141. package/dist/plugins/ui-builder/index.d.mts +2 -2
  142. package/dist/plugins/ui-builder/index.d.ts +2 -2
  143. package/dist/shared/{stack.C-WUPMT6.d.cts → stack.B2xZTSiO.d.cts} +4 -4
  144. package/dist/shared/{stack.B1EeBt1b.d.ts → stack.B58oHdqm.d.mts} +33 -3
  145. package/dist/shared/{stack.CVDTkMoO.d.mts → stack.B8QD11QU.d.cts} +7 -7
  146. package/dist/shared/{stack.CVDTkMoO.d.cts → stack.B8QD11QU.d.mts} +7 -7
  147. package/dist/shared/{stack.CVDTkMoO.d.ts → stack.B8QD11QU.d.ts} +7 -7
  148. package/dist/shared/{stack.CIP6QS9l.d.ts → stack.BDVEpue1.d.ts} +1 -1
  149. package/dist/shared/{stack.C5dtIncc.d.mts → stack.BTvbxZvw.d.cts} +1 -1
  150. package/dist/shared/{stack.DaOcgmrM.d.ts → stack.BV9hnvu4.d.cts} +31 -7
  151. package/dist/shared/{stack.DaOcgmrM.d.cts → stack.BV9hnvu4.d.mts} +31 -7
  152. package/dist/shared/{stack.DaOcgmrM.d.mts → stack.BV9hnvu4.d.ts} +31 -7
  153. package/dist/shared/{stack.DdI5W6MB.d.mts → stack.BozPgbrZ.d.cts} +19 -19
  154. package/dist/shared/{stack.DdI5W6MB.d.ts → stack.BozPgbrZ.d.mts} +19 -19
  155. package/dist/shared/{stack.DdI5W6MB.d.cts → stack.BozPgbrZ.d.ts} +19 -19
  156. package/dist/shared/{stack.CP68pFEH.d.mts → stack.C9Mg2Q46.d.cts} +33 -3
  157. package/dist/shared/{stack.BeSm90va.d.ts → stack.CTDVxbrA.d.ts} +72 -14
  158. package/dist/shared/{stack.C-Ptrz8s.d.ts → stack.Cj_zKww4.d.ts} +4 -4
  159. package/dist/shared/{stack.TIBF2AOx.d.ts → stack.CxaFNQCV.d.mts} +89 -34
  160. package/dist/shared/{stack.CMh_EdxW.d.cts → stack.D-b5zbPm.d.cts} +72 -14
  161. package/dist/shared/{stack.Dw0Ly2TM.d.cts → stack.DTtmJPQO.d.mts} +1 -1
  162. package/dist/shared/{stack.BKfolAyK.d.ts → stack.DXnclTG7.d.ts} +11 -11
  163. package/dist/shared/{stack.snB1EDP7.d.cts → stack.DaZM10cp.d.cts} +11 -11
  164. package/dist/shared/{stack.Dg09R0oB.d.mts → stack.FVWf2JhZ.d.mts} +72 -14
  165. package/dist/shared/{stack.BIXEI6v_.d.mts → stack.cfCkioTe.d.mts} +11 -11
  166. package/dist/shared/{stack.6fUOjLs9.d.mts → stack.dH7u-TJH.d.mts} +4 -4
  167. package/dist/shared/{stack.BpolpQpf.d.cts → stack.j75TpKh2.d.ts} +89 -34
  168. package/dist/shared/{stack.rTy7-wQU.d.mts → stack.n1_i1p2B.d.cts} +89 -34
  169. package/dist/shared/{stack.IdtKDRka.d.cts → stack.sO33ZDhK.d.ts} +33 -3
  170. package/package.json +14 -1
  171. package/src/client/components/compose.tsx +7 -4
  172. package/src/plugins/ai-chat/api/page-tools.ts +111 -0
  173. package/src/plugins/ai-chat/api/plugin.ts +228 -72
  174. package/src/plugins/ai-chat/client/components/chat-input.tsx +2 -2
  175. package/src/plugins/ai-chat/client/components/chat-interface.tsx +154 -58
  176. package/src/plugins/ai-chat/client/components/chat-layout.tsx +166 -32
  177. package/src/plugins/ai-chat/client/components/chat-sidebar.tsx +1 -1
  178. package/src/plugins/ai-chat/client/context/page-ai-context.tsx +240 -0
  179. package/src/plugins/ai-chat/client/plugin.tsx +23 -31
  180. package/src/plugins/ai-chat/schemas.ts +16 -0
  181. package/src/plugins/blog/api/plugin.ts +31 -47
  182. package/src/plugins/blog/client/components/forms/post-forms.tsx +29 -2
  183. package/src/plugins/blog/client/components/pages/edit-post-page.internal.tsx +28 -0
  184. package/src/plugins/blog/client/components/pages/fill-blog-form-handler.ts +38 -0
  185. package/src/plugins/blog/client/components/pages/new-post-page.internal.tsx +33 -1
  186. package/src/plugins/blog/client/components/pages/post-page.internal.tsx +20 -0
  187. package/src/plugins/blog/client/plugin.tsx +36 -39
  188. package/src/plugins/client/index.ts +5 -1
  189. package/src/plugins/cms/api/index.ts +4 -0
  190. package/src/plugins/cms/api/mutations.ts +84 -0
  191. package/src/plugins/cms/api/plugin.ts +23 -17
  192. package/src/plugins/cms/client/plugin.tsx +18 -21
  193. package/src/plugins/cms/types.ts +7 -7
  194. package/src/plugins/form-builder/api/plugin.ts +64 -64
  195. package/src/plugins/form-builder/client/plugin.tsx +19 -18
  196. package/src/plugins/form-builder/types.ts +19 -24
  197. package/src/plugins/kanban/api/index.ts +6 -0
  198. package/src/plugins/kanban/api/mutations.ts +169 -0
  199. package/src/plugins/kanban/api/plugin.ts +123 -136
  200. package/src/plugins/kanban/client/hooks/kanban-hooks.tsx +4 -0
  201. package/src/plugins/kanban/client/plugin.tsx +35 -41
  202. package/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.tsx +132 -0
  203. package/src/plugins/ui-builder/client/plugin.tsx +11 -10
  204. package/src/plugins/ui-builder/types.ts +4 -4
  205. package/src/plugins/utils.ts +92 -1
  206. package/dist/shared/{stack.CBON0dWL.d.mts → stack.BQmuNl5p.d.cts} +2 -2
  207. package/dist/shared/{stack.CBON0dWL.d.ts → stack.BQmuNl5p.d.mts} +2 -2
  208. package/dist/shared/{stack.CBON0dWL.d.cts → stack.BQmuNl5p.d.ts} +2 -2
@@ -2,10 +2,12 @@
2
2
 
3
3
  const api = require('@btst/stack/plugins/api');
4
4
  const db = require('../db.cjs');
5
- const utils = require('../utils.cjs');
5
+ const utils$1 = require('../utils.cjs');
6
6
  const schemas = require('../schemas.cjs');
7
7
  const getters = require('./getters.cjs');
8
+ const mutations = require('./mutations.cjs');
8
9
  const queryKeyDefs = require('./query-key-defs.cjs');
10
+ const utils = require('../../utils.cjs');
9
11
  const serializers = require('./serializers.cjs');
10
12
 
11
13
  function createKanbanPrefetchForRoute(adapter) {
@@ -39,7 +41,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
39
41
  api: (adapter) => ({
40
42
  getAllBoards: (params) => getters.getAllBoards(adapter, params),
41
43
  getBoardById: (id) => getters.getBoardById(adapter, id),
42
- prefetchForRoute: createKanbanPrefetchForRoute(adapter)
44
+ prefetchForRoute: createKanbanPrefetchForRoute(adapter),
45
+ // Mutations
46
+ createTask: (input) => mutations.createKanbanTask(adapter, input),
47
+ findOrCreateBoard: (slug, name, columnTitles) => mutations.findOrCreateKanbanBoard(adapter, slug, name, columnTitles),
48
+ getColumnsByBoardId: (boardId) => mutations.getKanbanColumnsByBoardId(adapter, boardId)
43
49
  }),
44
50
  routes: (adapter) => {
45
51
  const listBoards = api.createEndpoint(
@@ -53,12 +59,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
53
59
  const context = { query, headers };
54
60
  try {
55
61
  if (hooks?.onBeforeListBoards) {
56
- const canList = await hooks.onBeforeListBoards(query, context);
57
- if (!canList) {
58
- throw ctx.error(403, {
59
- message: "Unauthorized: Cannot list boards"
60
- });
61
- }
62
+ await utils.runHookWithShim(
63
+ () => hooks.onBeforeListBoards(query, context),
64
+ ctx.error,
65
+ "Unauthorized: Cannot list boards"
66
+ );
62
67
  }
63
68
  const result = await getters.getAllBoards(adapter, query);
64
69
  if (hooks?.onBoardsRead) {
@@ -83,12 +88,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
83
88
  const context = { params, headers };
84
89
  try {
85
90
  if (hooks?.onBeforeReadBoard) {
86
- const canRead = await hooks.onBeforeReadBoard(params.id, context);
87
- if (!canRead) {
88
- throw ctx.error(403, {
89
- message: "Unauthorized: Cannot read board"
90
- });
91
- }
91
+ await utils.runHookWithShim(
92
+ () => hooks.onBeforeReadBoard(params.id, context),
93
+ ctx.error,
94
+ "Unauthorized: Cannot read board"
95
+ );
92
96
  }
93
97
  const result = await getters.getBoardById(adapter, params.id);
94
98
  if (!result) {
@@ -119,18 +123,14 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
119
123
  };
120
124
  try {
121
125
  if (hooks?.onBeforeCreateBoard) {
122
- const canCreate = await hooks.onBeforeCreateBoard(
123
- ctx.body,
124
- context
126
+ await utils.runHookWithShim(
127
+ () => hooks.onBeforeCreateBoard(ctx.body, context),
128
+ ctx.error,
129
+ "Unauthorized: Cannot create board"
125
130
  );
126
- if (!canCreate) {
127
- throw ctx.error(403, {
128
- message: "Unauthorized: Cannot create board"
129
- });
130
- }
131
131
  }
132
132
  const { ...boardData } = ctx.body;
133
- const slug = utils.slugify(boardData.slug || boardData.name);
133
+ const slug = utils$1.slugify(boardData.slug || boardData.name);
134
134
  if (!slug) {
135
135
  throw ctx.error(400, {
136
136
  message: "Invalid slug: must contain at least one alphanumeric character"
@@ -197,19 +197,18 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
197
197
  };
198
198
  try {
199
199
  if (hooks?.onBeforeUpdateBoard) {
200
- const canUpdate = await hooks.onBeforeUpdateBoard(
201
- ctx.params.id,
202
- { ...ctx.body, id: ctx.params.id },
203
- context
200
+ await utils.runHookWithShim(
201
+ () => hooks.onBeforeUpdateBoard(
202
+ ctx.params.id,
203
+ { ...ctx.body, id: ctx.params.id },
204
+ context
205
+ ),
206
+ ctx.error,
207
+ "Unauthorized: Cannot update board"
204
208
  );
205
- if (!canUpdate) {
206
- throw ctx.error(403, {
207
- message: "Unauthorized: Cannot update board"
208
- });
209
- }
210
209
  }
211
210
  const { slug: rawSlug, ...restBoardData } = ctx.body;
212
- const slugified = rawSlug ? utils.slugify(rawSlug) : void 0;
211
+ const slugified = rawSlug ? utils$1.slugify(rawSlug) : void 0;
213
212
  if (rawSlug && !slugified) {
214
213
  throw ctx.error(400, {
215
214
  message: "Invalid slug: must contain at least one alphanumeric character"
@@ -263,15 +262,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
263
262
  throw ctx.error(404, { message: "Board not found" });
264
263
  }
265
264
  if (hooks?.onBeforeDeleteBoard) {
266
- const canDelete = await hooks.onBeforeDeleteBoard(
267
- ctx.params.id,
268
- context
265
+ await utils.runHookWithShim(
266
+ () => hooks.onBeforeDeleteBoard(ctx.params.id, context),
267
+ ctx.error,
268
+ "Unauthorized: Cannot delete board"
269
269
  );
270
- if (!canDelete) {
271
- throw ctx.error(403, {
272
- message: "Unauthorized: Cannot delete board"
273
- });
274
- }
275
270
  }
276
271
  await adapter.delete({
277
272
  model: "kanbanBoard",
@@ -302,15 +297,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
302
297
  };
303
298
  try {
304
299
  if (hooks?.onBeforeCreateColumn) {
305
- const canCreate = await hooks.onBeforeCreateColumn(
306
- ctx.body,
307
- context
300
+ await utils.runHookWithShim(
301
+ () => hooks.onBeforeCreateColumn(ctx.body, context),
302
+ ctx.error,
303
+ "Unauthorized: Cannot create column"
308
304
  );
309
- if (!canCreate) {
310
- throw ctx.error(403, {
311
- message: "Unauthorized: Cannot create column"
312
- });
313
- }
314
305
  }
315
306
  const existingColumns = await adapter.findMany({
316
307
  model: "kanbanColumn",
@@ -355,16 +346,15 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
355
346
  };
356
347
  try {
357
348
  if (hooks?.onBeforeUpdateColumn) {
358
- const canUpdate = await hooks.onBeforeUpdateColumn(
359
- ctx.params.id,
360
- { ...ctx.body, id: ctx.params.id },
361
- context
349
+ await utils.runHookWithShim(
350
+ () => hooks.onBeforeUpdateColumn(
351
+ ctx.params.id,
352
+ { ...ctx.body, id: ctx.params.id },
353
+ context
354
+ ),
355
+ ctx.error,
356
+ "Unauthorized: Cannot update column"
362
357
  );
363
- if (!canUpdate) {
364
- throw ctx.error(403, {
365
- message: "Unauthorized: Cannot update column"
366
- });
367
- }
368
358
  }
369
359
  const updated = await adapter.update({
370
360
  model: "kanbanColumn",
@@ -407,15 +397,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
407
397
  throw ctx.error(404, { message: "Column not found" });
408
398
  }
409
399
  if (hooks?.onBeforeDeleteColumn) {
410
- const canDelete = await hooks.onBeforeDeleteColumn(
411
- ctx.params.id,
412
- context
400
+ await utils.runHookWithShim(
401
+ () => hooks.onBeforeDeleteColumn(ctx.params.id, context),
402
+ ctx.error,
403
+ "Unauthorized: Cannot delete column"
413
404
  );
414
- if (!canDelete) {
415
- throw ctx.error(403, {
416
- message: "Unauthorized: Cannot delete column"
417
- });
418
- }
419
405
  }
420
406
  await adapter.delete({
421
407
  model: "kanbanColumn",
@@ -446,16 +432,15 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
446
432
  for (let i = 0; i < columnIds.length; i++) {
447
433
  const columnId = columnIds[i];
448
434
  if (!columnId) continue;
449
- const canUpdate = await hooks.onBeforeUpdateColumn(
450
- columnId,
451
- { id: columnId, order: i },
452
- context
435
+ await utils.runHookWithShim(
436
+ () => hooks.onBeforeUpdateColumn(
437
+ columnId,
438
+ { id: columnId, order: i },
439
+ context
440
+ ),
441
+ ctx.error,
442
+ "Unauthorized: Cannot reorder columns"
453
443
  );
454
- if (!canUpdate) {
455
- throw ctx.error(403, {
456
- message: "Unauthorized: Cannot reorder columns"
457
- });
458
- }
459
444
  }
460
445
  }
461
446
  const updatedColumns = [];
@@ -497,15 +482,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
497
482
  };
498
483
  try {
499
484
  if (hooks?.onBeforeCreateTask) {
500
- const canCreate = await hooks.onBeforeCreateTask(
501
- ctx.body,
502
- context
485
+ await utils.runHookWithShim(
486
+ () => hooks.onBeforeCreateTask(ctx.body, context),
487
+ ctx.error,
488
+ "Unauthorized: Cannot create task"
503
489
  );
504
- if (!canCreate) {
505
- throw ctx.error(403, {
506
- message: "Unauthorized: Cannot create task"
507
- });
508
- }
509
490
  }
510
491
  const existingTasks = await adapter.findMany({
511
492
  model: "kanbanTask",
@@ -556,16 +537,15 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
556
537
  };
557
538
  try {
558
539
  if (hooks?.onBeforeUpdateTask) {
559
- const canUpdate = await hooks.onBeforeUpdateTask(
560
- ctx.params.id,
561
- { ...ctx.body, id: ctx.params.id },
562
- context
540
+ await utils.runHookWithShim(
541
+ () => hooks.onBeforeUpdateTask(
542
+ ctx.params.id,
543
+ { ...ctx.body, id: ctx.params.id },
544
+ context
545
+ ),
546
+ ctx.error,
547
+ "Unauthorized: Cannot update task"
563
548
  );
564
- if (!canUpdate) {
565
- throw ctx.error(403, {
566
- message: "Unauthorized: Cannot update task"
567
- });
568
- }
569
549
  }
570
550
  const updated = await adapter.update({
571
551
  model: "kanbanTask",
@@ -608,15 +588,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
608
588
  throw ctx.error(404, { message: "Task not found" });
609
589
  }
610
590
  if (hooks?.onBeforeDeleteTask) {
611
- const canDelete = await hooks.onBeforeDeleteTask(
612
- ctx.params.id,
613
- context
591
+ await utils.runHookWithShim(
592
+ () => hooks.onBeforeDeleteTask(ctx.params.id, context),
593
+ ctx.error,
594
+ "Unauthorized: Cannot delete task"
614
595
  );
615
- if (!canDelete) {
616
- throw ctx.error(403, {
617
- message: "Unauthorized: Cannot delete task"
618
- });
619
- }
620
596
  }
621
597
  await adapter.delete({
622
598
  model: "kanbanTask",
@@ -651,16 +627,15 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
651
627
  throw ctx.error(404, { message: "Task not found" });
652
628
  }
653
629
  if (hooks?.onBeforeUpdateTask) {
654
- const canUpdate = await hooks.onBeforeUpdateTask(
655
- taskId,
656
- { id: taskId, columnId: targetColumnId, order: targetOrder },
657
- context
630
+ await utils.runHookWithShim(
631
+ () => hooks.onBeforeUpdateTask(
632
+ taskId,
633
+ { id: taskId, columnId: targetColumnId, order: targetOrder },
634
+ context
635
+ ),
636
+ ctx.error,
637
+ "Unauthorized: Cannot move task"
658
638
  );
659
- if (!canUpdate) {
660
- throw ctx.error(403, {
661
- message: "Unauthorized: Cannot move task"
662
- });
663
- }
664
639
  }
665
640
  const updated = await adapter.update({
666
641
  model: "kanbanTask",
@@ -696,16 +671,15 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
696
671
  for (let i = 0; i < taskIds.length; i++) {
697
672
  const taskId = taskIds[i];
698
673
  if (!taskId) continue;
699
- const canUpdate = await hooks.onBeforeUpdateTask(
700
- taskId,
701
- { id: taskId, order: i },
702
- context
674
+ await utils.runHookWithShim(
675
+ () => hooks.onBeforeUpdateTask(
676
+ taskId,
677
+ { id: taskId, order: i },
678
+ context
679
+ ),
680
+ ctx.error,
681
+ "Unauthorized: Cannot reorder tasks"
703
682
  );
704
- if (!canUpdate) {
705
- throw ctx.error(403, {
706
- message: "Unauthorized: Cannot reorder tasks"
707
- });
708
- }
709
683
  }
710
684
  }
711
685
  const updatedTasks = [];
@@ -3,7 +3,9 @@ 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';
6
7
  import { KANBAN_QUERY_KEYS } from './query-key-defs.mjs';
8
+ import { runHookWithShim } from '../../utils.mjs';
7
9
  import { serializeBoard } from './serializers.mjs';
8
10
 
9
11
  function createKanbanPrefetchForRoute(adapter) {
@@ -37,7 +39,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
37
39
  api: (adapter) => ({
38
40
  getAllBoards: (params) => getAllBoards(adapter, params),
39
41
  getBoardById: (id) => getBoardById(adapter, id),
40
- prefetchForRoute: createKanbanPrefetchForRoute(adapter)
42
+ prefetchForRoute: createKanbanPrefetchForRoute(adapter),
43
+ // Mutations
44
+ createTask: (input) => createKanbanTask(adapter, input),
45
+ findOrCreateBoard: (slug, name, columnTitles) => findOrCreateKanbanBoard(adapter, slug, name, columnTitles),
46
+ getColumnsByBoardId: (boardId) => getKanbanColumnsByBoardId(adapter, boardId)
41
47
  }),
42
48
  routes: (adapter) => {
43
49
  const listBoards = createEndpoint(
@@ -51,12 +57,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
51
57
  const context = { query, headers };
52
58
  try {
53
59
  if (hooks?.onBeforeListBoards) {
54
- const canList = await hooks.onBeforeListBoards(query, context);
55
- if (!canList) {
56
- throw ctx.error(403, {
57
- message: "Unauthorized: Cannot list boards"
58
- });
59
- }
60
+ await runHookWithShim(
61
+ () => hooks.onBeforeListBoards(query, context),
62
+ ctx.error,
63
+ "Unauthorized: Cannot list boards"
64
+ );
60
65
  }
61
66
  const result = await getAllBoards(adapter, query);
62
67
  if (hooks?.onBoardsRead) {
@@ -81,12 +86,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
81
86
  const context = { params, headers };
82
87
  try {
83
88
  if (hooks?.onBeforeReadBoard) {
84
- const canRead = await hooks.onBeforeReadBoard(params.id, context);
85
- if (!canRead) {
86
- throw ctx.error(403, {
87
- message: "Unauthorized: Cannot read board"
88
- });
89
- }
89
+ await runHookWithShim(
90
+ () => hooks.onBeforeReadBoard(params.id, context),
91
+ ctx.error,
92
+ "Unauthorized: Cannot read board"
93
+ );
90
94
  }
91
95
  const result = await getBoardById(adapter, params.id);
92
96
  if (!result) {
@@ -117,15 +121,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
117
121
  };
118
122
  try {
119
123
  if (hooks?.onBeforeCreateBoard) {
120
- const canCreate = await hooks.onBeforeCreateBoard(
121
- ctx.body,
122
- context
124
+ await runHookWithShim(
125
+ () => hooks.onBeforeCreateBoard(ctx.body, context),
126
+ ctx.error,
127
+ "Unauthorized: Cannot create board"
123
128
  );
124
- if (!canCreate) {
125
- throw ctx.error(403, {
126
- message: "Unauthorized: Cannot create board"
127
- });
128
- }
129
129
  }
130
130
  const { ...boardData } = ctx.body;
131
131
  const slug = slugify(boardData.slug || boardData.name);
@@ -195,16 +195,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
195
195
  };
196
196
  try {
197
197
  if (hooks?.onBeforeUpdateBoard) {
198
- const canUpdate = await hooks.onBeforeUpdateBoard(
199
- ctx.params.id,
200
- { ...ctx.body, id: ctx.params.id },
201
- context
198
+ await runHookWithShim(
199
+ () => hooks.onBeforeUpdateBoard(
200
+ ctx.params.id,
201
+ { ...ctx.body, id: ctx.params.id },
202
+ context
203
+ ),
204
+ ctx.error,
205
+ "Unauthorized: Cannot update board"
202
206
  );
203
- if (!canUpdate) {
204
- throw ctx.error(403, {
205
- message: "Unauthorized: Cannot update board"
206
- });
207
- }
208
207
  }
209
208
  const { slug: rawSlug, ...restBoardData } = ctx.body;
210
209
  const slugified = rawSlug ? slugify(rawSlug) : void 0;
@@ -261,15 +260,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
261
260
  throw ctx.error(404, { message: "Board not found" });
262
261
  }
263
262
  if (hooks?.onBeforeDeleteBoard) {
264
- const canDelete = await hooks.onBeforeDeleteBoard(
265
- ctx.params.id,
266
- context
263
+ await runHookWithShim(
264
+ () => hooks.onBeforeDeleteBoard(ctx.params.id, context),
265
+ ctx.error,
266
+ "Unauthorized: Cannot delete board"
267
267
  );
268
- if (!canDelete) {
269
- throw ctx.error(403, {
270
- message: "Unauthorized: Cannot delete board"
271
- });
272
- }
273
268
  }
274
269
  await adapter.delete({
275
270
  model: "kanbanBoard",
@@ -300,15 +295,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
300
295
  };
301
296
  try {
302
297
  if (hooks?.onBeforeCreateColumn) {
303
- const canCreate = await hooks.onBeforeCreateColumn(
304
- ctx.body,
305
- context
298
+ await runHookWithShim(
299
+ () => hooks.onBeforeCreateColumn(ctx.body, context),
300
+ ctx.error,
301
+ "Unauthorized: Cannot create column"
306
302
  );
307
- if (!canCreate) {
308
- throw ctx.error(403, {
309
- message: "Unauthorized: Cannot create column"
310
- });
311
- }
312
303
  }
313
304
  const existingColumns = await adapter.findMany({
314
305
  model: "kanbanColumn",
@@ -353,16 +344,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
353
344
  };
354
345
  try {
355
346
  if (hooks?.onBeforeUpdateColumn) {
356
- const canUpdate = await hooks.onBeforeUpdateColumn(
357
- ctx.params.id,
358
- { ...ctx.body, id: ctx.params.id },
359
- context
347
+ await runHookWithShim(
348
+ () => hooks.onBeforeUpdateColumn(
349
+ ctx.params.id,
350
+ { ...ctx.body, id: ctx.params.id },
351
+ context
352
+ ),
353
+ ctx.error,
354
+ "Unauthorized: Cannot update column"
360
355
  );
361
- if (!canUpdate) {
362
- throw ctx.error(403, {
363
- message: "Unauthorized: Cannot update column"
364
- });
365
- }
366
356
  }
367
357
  const updated = await adapter.update({
368
358
  model: "kanbanColumn",
@@ -405,15 +395,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
405
395
  throw ctx.error(404, { message: "Column not found" });
406
396
  }
407
397
  if (hooks?.onBeforeDeleteColumn) {
408
- const canDelete = await hooks.onBeforeDeleteColumn(
409
- ctx.params.id,
410
- context
398
+ await runHookWithShim(
399
+ () => hooks.onBeforeDeleteColumn(ctx.params.id, context),
400
+ ctx.error,
401
+ "Unauthorized: Cannot delete column"
411
402
  );
412
- if (!canDelete) {
413
- throw ctx.error(403, {
414
- message: "Unauthorized: Cannot delete column"
415
- });
416
- }
417
403
  }
418
404
  await adapter.delete({
419
405
  model: "kanbanColumn",
@@ -444,16 +430,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
444
430
  for (let i = 0; i < columnIds.length; i++) {
445
431
  const columnId = columnIds[i];
446
432
  if (!columnId) continue;
447
- const canUpdate = await hooks.onBeforeUpdateColumn(
448
- columnId,
449
- { id: columnId, order: i },
450
- context
433
+ await runHookWithShim(
434
+ () => hooks.onBeforeUpdateColumn(
435
+ columnId,
436
+ { id: columnId, order: i },
437
+ context
438
+ ),
439
+ ctx.error,
440
+ "Unauthorized: Cannot reorder columns"
451
441
  );
452
- if (!canUpdate) {
453
- throw ctx.error(403, {
454
- message: "Unauthorized: Cannot reorder columns"
455
- });
456
- }
457
442
  }
458
443
  }
459
444
  const updatedColumns = [];
@@ -495,15 +480,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
495
480
  };
496
481
  try {
497
482
  if (hooks?.onBeforeCreateTask) {
498
- const canCreate = await hooks.onBeforeCreateTask(
499
- ctx.body,
500
- context
483
+ await runHookWithShim(
484
+ () => hooks.onBeforeCreateTask(ctx.body, context),
485
+ ctx.error,
486
+ "Unauthorized: Cannot create task"
501
487
  );
502
- if (!canCreate) {
503
- throw ctx.error(403, {
504
- message: "Unauthorized: Cannot create task"
505
- });
506
- }
507
488
  }
508
489
  const existingTasks = await adapter.findMany({
509
490
  model: "kanbanTask",
@@ -554,16 +535,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
554
535
  };
555
536
  try {
556
537
  if (hooks?.onBeforeUpdateTask) {
557
- const canUpdate = await hooks.onBeforeUpdateTask(
558
- ctx.params.id,
559
- { ...ctx.body, id: ctx.params.id },
560
- context
538
+ await runHookWithShim(
539
+ () => hooks.onBeforeUpdateTask(
540
+ ctx.params.id,
541
+ { ...ctx.body, id: ctx.params.id },
542
+ context
543
+ ),
544
+ ctx.error,
545
+ "Unauthorized: Cannot update task"
561
546
  );
562
- if (!canUpdate) {
563
- throw ctx.error(403, {
564
- message: "Unauthorized: Cannot update task"
565
- });
566
- }
567
547
  }
568
548
  const updated = await adapter.update({
569
549
  model: "kanbanTask",
@@ -606,15 +586,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
606
586
  throw ctx.error(404, { message: "Task not found" });
607
587
  }
608
588
  if (hooks?.onBeforeDeleteTask) {
609
- const canDelete = await hooks.onBeforeDeleteTask(
610
- ctx.params.id,
611
- context
589
+ await runHookWithShim(
590
+ () => hooks.onBeforeDeleteTask(ctx.params.id, context),
591
+ ctx.error,
592
+ "Unauthorized: Cannot delete task"
612
593
  );
613
- if (!canDelete) {
614
- throw ctx.error(403, {
615
- message: "Unauthorized: Cannot delete task"
616
- });
617
- }
618
594
  }
619
595
  await adapter.delete({
620
596
  model: "kanbanTask",
@@ -649,16 +625,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
649
625
  throw ctx.error(404, { message: "Task not found" });
650
626
  }
651
627
  if (hooks?.onBeforeUpdateTask) {
652
- const canUpdate = await hooks.onBeforeUpdateTask(
653
- taskId,
654
- { id: taskId, columnId: targetColumnId, order: targetOrder },
655
- context
628
+ await runHookWithShim(
629
+ () => hooks.onBeforeUpdateTask(
630
+ taskId,
631
+ { id: taskId, columnId: targetColumnId, order: targetOrder },
632
+ context
633
+ ),
634
+ ctx.error,
635
+ "Unauthorized: Cannot move task"
656
636
  );
657
- if (!canUpdate) {
658
- throw ctx.error(403, {
659
- message: "Unauthorized: Cannot move task"
660
- });
661
- }
662
637
  }
663
638
  const updated = await adapter.update({
664
639
  model: "kanbanTask",
@@ -694,16 +669,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
694
669
  for (let i = 0; i < taskIds.length; i++) {
695
670
  const taskId = taskIds[i];
696
671
  if (!taskId) continue;
697
- const canUpdate = await hooks.onBeforeUpdateTask(
698
- taskId,
699
- { id: taskId, order: i },
700
- context
672
+ await runHookWithShim(
673
+ () => hooks.onBeforeUpdateTask(
674
+ taskId,
675
+ { id: taskId, order: i },
676
+ context
677
+ ),
678
+ ctx.error,
679
+ "Unauthorized: Cannot reorder tasks"
701
680
  );
702
- if (!canUpdate) {
703
- throw ctx.error(403, {
704
- message: "Unauthorized: Cannot reorder tasks"
705
- });
706
- }
707
681
  }
708
682
  }
709
683
  const updatedTasks = [];