@btst/stack 2.4.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 (136) hide show
  1. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.cjs +33 -47
  2. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +33 -47
  3. package/dist/packages/stack/src/plugins/ai-chat/client/plugin.cjs +14 -21
  4. package/dist/packages/stack/src/plugins/ai-chat/client/plugin.mjs +15 -22
  5. package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +28 -45
  6. package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +22 -39
  7. package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +23 -27
  8. package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +24 -28
  9. package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +14 -17
  10. package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +14 -17
  11. package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +11 -15
  12. package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +12 -16
  13. package/dist/packages/stack/src/plugins/form-builder/api/plugin.cjs +58 -62
  14. package/dist/packages/stack/src/plugins/form-builder/api/plugin.mjs +58 -62
  15. package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +12 -12
  16. package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +13 -13
  17. package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +86 -117
  18. package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +83 -114
  19. package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +22 -29
  20. package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +23 -30
  21. package/dist/packages/stack/src/plugins/ui-builder/client/plugin.cjs +8 -8
  22. package/dist/packages/stack/src/plugins/ui-builder/client/plugin.mjs +9 -9
  23. package/dist/packages/stack/src/plugins/utils.cjs +42 -0
  24. package/dist/packages/stack/src/plugins/utils.mjs +41 -1
  25. package/dist/plugins/ai-chat/api/index.d.cts +1 -1
  26. package/dist/plugins/ai-chat/api/index.d.mts +1 -1
  27. package/dist/plugins/ai-chat/api/index.d.ts +1 -1
  28. package/dist/plugins/ai-chat/client/hooks/index.d.cts +1 -1
  29. package/dist/plugins/ai-chat/client/hooks/index.d.mts +1 -1
  30. package/dist/plugins/ai-chat/client/hooks/index.d.ts +1 -1
  31. package/dist/plugins/ai-chat/client/index.d.cts +8 -8
  32. package/dist/plugins/ai-chat/client/index.d.mts +8 -8
  33. package/dist/plugins/ai-chat/client/index.d.ts +8 -8
  34. package/dist/plugins/ai-chat/query-keys.d.cts +1 -1
  35. package/dist/plugins/ai-chat/query-keys.d.mts +1 -1
  36. package/dist/plugins/ai-chat/query-keys.d.ts +1 -1
  37. package/dist/plugins/blog/api/index.d.cts +1 -1
  38. package/dist/plugins/blog/api/index.d.mts +1 -1
  39. package/dist/plugins/blog/api/index.d.ts +1 -1
  40. package/dist/plugins/blog/client/index.d.cts +12 -12
  41. package/dist/plugins/blog/client/index.d.mts +12 -12
  42. package/dist/plugins/blog/client/index.d.ts +12 -12
  43. package/dist/plugins/blog/query-keys.d.cts +1 -1
  44. package/dist/plugins/blog/query-keys.d.mts +1 -1
  45. package/dist/plugins/blog/query-keys.d.ts +1 -1
  46. package/dist/plugins/client/index.cjs +1 -0
  47. package/dist/plugins/client/index.d.cts +8 -1
  48. package/dist/plugins/client/index.d.mts +8 -1
  49. package/dist/plugins/client/index.d.ts +8 -1
  50. package/dist/plugins/client/index.mjs +1 -1
  51. package/dist/plugins/cms/api/index.d.cts +2 -2
  52. package/dist/plugins/cms/api/index.d.mts +2 -2
  53. package/dist/plugins/cms/api/index.d.ts +2 -2
  54. package/dist/plugins/cms/client/hooks/index.d.cts +1 -1
  55. package/dist/plugins/cms/client/hooks/index.d.mts +1 -1
  56. package/dist/plugins/cms/client/hooks/index.d.ts +1 -1
  57. package/dist/plugins/cms/client/index.d.cts +6 -6
  58. package/dist/plugins/cms/client/index.d.mts +6 -6
  59. package/dist/plugins/cms/client/index.d.ts +6 -6
  60. package/dist/plugins/cms/query-keys.d.cts +2 -2
  61. package/dist/plugins/cms/query-keys.d.mts +2 -2
  62. package/dist/plugins/cms/query-keys.d.ts +2 -2
  63. package/dist/plugins/form-builder/api/index.d.cts +2 -2
  64. package/dist/plugins/form-builder/api/index.d.mts +2 -2
  65. package/dist/plugins/form-builder/api/index.d.ts +2 -2
  66. package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
  67. package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
  68. package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
  69. package/dist/plugins/form-builder/client/hooks/index.d.cts +1 -1
  70. package/dist/plugins/form-builder/client/hooks/index.d.mts +1 -1
  71. package/dist/plugins/form-builder/client/hooks/index.d.ts +1 -1
  72. package/dist/plugins/form-builder/client/index.d.cts +6 -6
  73. package/dist/plugins/form-builder/client/index.d.mts +6 -6
  74. package/dist/plugins/form-builder/client/index.d.ts +6 -6
  75. package/dist/plugins/form-builder/query-keys.d.cts +2 -2
  76. package/dist/plugins/form-builder/query-keys.d.mts +2 -2
  77. package/dist/plugins/form-builder/query-keys.d.ts +2 -2
  78. package/dist/plugins/kanban/api/index.d.cts +1 -1
  79. package/dist/plugins/kanban/api/index.d.mts +1 -1
  80. package/dist/plugins/kanban/api/index.d.ts +1 -1
  81. package/dist/plugins/kanban/client/index.d.cts +12 -12
  82. package/dist/plugins/kanban/client/index.d.mts +12 -12
  83. package/dist/plugins/kanban/client/index.d.ts +12 -12
  84. package/dist/plugins/kanban/query-keys.d.cts +1 -1
  85. package/dist/plugins/kanban/query-keys.d.mts +1 -1
  86. package/dist/plugins/kanban/query-keys.d.ts +1 -1
  87. package/dist/plugins/ui-builder/client/hooks/index.d.cts +1 -1
  88. package/dist/plugins/ui-builder/client/hooks/index.d.mts +1 -1
  89. package/dist/plugins/ui-builder/client/hooks/index.d.ts +1 -1
  90. package/dist/plugins/ui-builder/client/index.d.cts +3 -3
  91. package/dist/plugins/ui-builder/client/index.d.mts +3 -3
  92. package/dist/plugins/ui-builder/client/index.d.ts +3 -3
  93. package/dist/plugins/ui-builder/index.d.cts +2 -2
  94. package/dist/plugins/ui-builder/index.d.mts +2 -2
  95. package/dist/plugins/ui-builder/index.d.ts +2 -2
  96. package/dist/shared/{stack.C-WUPMT6.d.cts → stack.B2xZTSiO.d.cts} +4 -4
  97. package/dist/shared/{stack.CczspVn2.d.mts → stack.B58oHdqm.d.mts} +1 -1
  98. package/dist/shared/{stack.CVDTkMoO.d.mts → stack.B8QD11QU.d.cts} +7 -7
  99. package/dist/shared/{stack.CVDTkMoO.d.cts → stack.B8QD11QU.d.mts} +7 -7
  100. package/dist/shared/{stack.CVDTkMoO.d.ts → stack.B8QD11QU.d.ts} +7 -7
  101. package/dist/shared/{stack.Kq2-QzOC.d.ts → stack.BDVEpue1.d.ts} +2 -2
  102. package/dist/shared/{stack.B7ONvlD_.d.mts → stack.BTvbxZvw.d.cts} +2 -2
  103. package/dist/shared/{stack.DdI5W6MB.d.mts → stack.BozPgbrZ.d.cts} +19 -19
  104. package/dist/shared/{stack.DdI5W6MB.d.cts → stack.BozPgbrZ.d.mts} +19 -19
  105. package/dist/shared/{stack.DdI5W6MB.d.ts → stack.BozPgbrZ.d.ts} +19 -19
  106. package/dist/shared/{stack.BUkC2EsZ.d.cts → stack.C9Mg2Q46.d.cts} +1 -1
  107. package/dist/shared/{stack.BEn34wW6.d.ts → stack.CTDVxbrA.d.ts} +12 -12
  108. package/dist/shared/{stack.C-Ptrz8s.d.ts → stack.Cj_zKww4.d.ts} +4 -4
  109. package/dist/shared/{stack.BepFXT3w.d.mts → stack.CxaFNQCV.d.mts} +25 -25
  110. package/dist/shared/{stack.DWoCZff7.d.cts → stack.D-b5zbPm.d.cts} +12 -12
  111. package/dist/shared/{stack.kcdnD4gA.d.cts → stack.DTtmJPQO.d.mts} +2 -2
  112. package/dist/shared/{stack.CL8ts1Mu.d.ts → stack.DXnclTG7.d.ts} +8 -8
  113. package/dist/shared/{stack.heOA9gzA.d.cts → stack.DaZM10cp.d.cts} +8 -8
  114. package/dist/shared/{stack.DTDxgFj8.d.mts → stack.FVWf2JhZ.d.mts} +12 -12
  115. package/dist/shared/{stack.Dk5r4W1F.d.mts → stack.cfCkioTe.d.mts} +8 -8
  116. package/dist/shared/{stack.6fUOjLs9.d.mts → stack.dH7u-TJH.d.mts} +4 -4
  117. package/dist/shared/{stack.CgWzG5jH.d.ts → stack.j75TpKh2.d.ts} +25 -25
  118. package/dist/shared/{stack.D3GB6wKv.d.cts → stack.n1_i1p2B.d.cts} +25 -25
  119. package/dist/shared/{stack.DASmUVjX.d.ts → stack.sO33ZDhK.d.ts} +1 -1
  120. package/package.json +1 -1
  121. package/src/plugins/ai-chat/api/plugin.ts +48 -63
  122. package/src/plugins/ai-chat/client/plugin.tsx +23 -31
  123. package/src/plugins/blog/api/plugin.ts +31 -47
  124. package/src/plugins/blog/client/plugin.tsx +36 -39
  125. package/src/plugins/client/index.ts +5 -1
  126. package/src/plugins/cms/api/plugin.ts +14 -17
  127. package/src/plugins/cms/client/plugin.tsx +18 -21
  128. package/src/plugins/cms/types.ts +7 -7
  129. package/src/plugins/form-builder/api/plugin.ts +64 -64
  130. package/src/plugins/form-builder/client/plugin.tsx +19 -18
  131. package/src/plugins/form-builder/types.ts +19 -24
  132. package/src/plugins/kanban/api/plugin.ts +111 -136
  133. package/src/plugins/kanban/client/plugin.tsx +35 -41
  134. package/src/plugins/ui-builder/client/plugin.tsx +11 -10
  135. package/src/plugins/ui-builder/types.ts +4 -4
  136. package/src/plugins/utils.ts +92 -1
@@ -6,6 +6,7 @@ import { listFormsQuerySchema, createFormSchema, updateFormSchema, listSubmissio
6
6
  import { extractUserAgent, extractIpAddress, slugify } from '../utils.mjs';
7
7
  import { getFormSubmissions, getFormBySlug, getFormById, getAllForms, serializeForm, serializeFormSubmission, serializeFormSubmissionWithData } from './getters.mjs';
8
8
  import { FORM_QUERY_KEYS } from './query-key-defs.mjs';
9
+ import { runHookWithShim } from '../../utils.mjs';
9
10
 
10
11
  function createFormBuilderPrefetchForRoute(adapter) {
11
12
  return async function prefetchForRoute(key, qc, params) {
@@ -96,10 +97,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
96
97
  const { status, limit, offset } = ctx.query;
97
98
  const context = createContext(ctx.headers);
98
99
  if (config.hooks?.onBeforeListForms) {
99
- const canList = await config.hooks.onBeforeListForms(context);
100
- if (!canList) {
101
- throw ctx.error(403, { message: "Access denied" });
102
- }
100
+ await runHookWithShim(
101
+ () => config.hooks.onBeforeListForms(context),
102
+ ctx.error,
103
+ "Access denied"
104
+ );
103
105
  }
104
106
  return getAllForms(adapter, { status, limit, offset });
105
107
  }
@@ -114,10 +116,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
114
116
  const { slug } = ctx.params;
115
117
  const context = createContext(ctx.headers);
116
118
  if (config.hooks?.onBeforeGetForm) {
117
- const canGet = await config.hooks.onBeforeGetForm(slug, context);
118
- if (!canGet) {
119
- throw ctx.error(403, { message: "Access denied" });
120
- }
119
+ await runHookWithShim(
120
+ () => config.hooks.onBeforeGetForm(slug, context),
121
+ ctx.error,
122
+ "Access denied"
123
+ );
121
124
  }
122
125
  const form = await getFormBySlug(adapter, slug);
123
126
  if (!form) {
@@ -136,10 +139,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
136
139
  const { id } = ctx.params;
137
140
  const context = createContext(ctx.headers);
138
141
  if (config.hooks?.onBeforeGetForm) {
139
- const canGet = await config.hooks.onBeforeGetForm(id, context);
140
- if (!canGet) {
141
- throw ctx.error(403, { message: "Access denied" });
142
- }
142
+ await runHookWithShim(
143
+ () => config.hooks.onBeforeGetForm(id, context),
144
+ ctx.error,
145
+ "Access denied"
146
+ );
143
147
  }
144
148
  const form = await adapter.findOne({
145
149
  model: "form",
@@ -190,15 +194,13 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
190
194
  status: body.status
191
195
  };
192
196
  if (config.hooks?.onBeforeFormCreated) {
193
- const result = await config.hooks.onBeforeFormCreated(
194
- formInput,
195
- context
197
+ const hookResult = await runHookWithShim(
198
+ () => config.hooks.onBeforeFormCreated(formInput, context),
199
+ ctx.error,
200
+ "Create operation denied"
196
201
  );
197
- if (result === false) {
198
- throw ctx.error(403, { message: "Create operation denied" });
199
- }
200
- if (result && typeof result === "object") {
201
- formInput = result;
202
+ if (hookResult && typeof hookResult === "object") {
203
+ formInput = hookResult;
202
204
  }
203
205
  }
204
206
  const form = await adapter.create({
@@ -280,16 +282,13 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
280
282
  status: body.status
281
283
  };
282
284
  if (config.hooks?.onBeforeFormUpdated) {
283
- const result = await config.hooks.onBeforeFormUpdated(
284
- id,
285
- updateInput,
286
- context
285
+ const hookResult = await runHookWithShim(
286
+ () => config.hooks.onBeforeFormUpdated(id, updateInput, context),
287
+ ctx.error,
288
+ "Update operation denied"
287
289
  );
288
- if (result === false) {
289
- throw ctx.error(403, { message: "Update operation denied" });
290
- }
291
- if (result && typeof result === "object") {
292
- updateInput = result;
290
+ if (hookResult && typeof hookResult === "object") {
291
+ updateInput = hookResult;
293
292
  }
294
293
  }
295
294
  const updateData = {
@@ -341,13 +340,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
341
340
  throw ctx.error(404, { message: "Form not found" });
342
341
  }
343
342
  if (config.hooks?.onBeforeFormDeleted) {
344
- const canDelete = await config.hooks.onBeforeFormDeleted(
345
- id,
346
- context
343
+ await runHookWithShim(
344
+ () => config.hooks.onBeforeFormDeleted(id, context),
345
+ ctx.error,
346
+ "Delete operation denied"
347
347
  );
348
- if (!canDelete) {
349
- throw ctx.error(403, { message: "Delete operation denied" });
350
- }
351
348
  }
352
349
  await adapter.delete({
353
350
  model: "formSubmission",
@@ -412,28 +409,33 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
412
409
  }
413
410
  let finalData = data;
414
411
  if (config.hooks?.onBeforeSubmission) {
412
+ let hookResult;
413
+ let originalError;
415
414
  try {
416
- const result = await config.hooks.onBeforeSubmission(
415
+ hookResult = await config.hooks.onBeforeSubmission(
417
416
  slug,
418
417
  data,
419
418
  submissionContext
420
419
  );
421
- if (result === false) {
422
- throw ctx.error(400, { message: "Submission rejected" });
423
- }
424
- if (result && typeof result === "object") {
425
- finalData = result;
420
+ if (hookResult === false) {
421
+ originalError = new Error("Submission rejected");
426
422
  }
427
- } catch (error) {
423
+ } catch (e) {
424
+ originalError = e instanceof Error ? e : new Error("Submission rejected");
425
+ }
426
+ if (originalError) {
428
427
  if (config.hooks?.onSubmissionError) {
429
428
  await config.hooks.onSubmissionError(
430
- error,
429
+ originalError,
431
430
  slug,
432
431
  data,
433
432
  submissionContext
434
433
  );
435
434
  }
436
- throw error;
435
+ throw ctx.error(400, { message: originalError.message });
436
+ }
437
+ if (hookResult && typeof hookResult === "object") {
438
+ finalData = hookResult;
437
439
  }
438
440
  }
439
441
  const submission = await adapter.create({
@@ -482,13 +484,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
482
484
  throw ctx.error(404, { message: "Form not found" });
483
485
  }
484
486
  if (config.hooks?.onBeforeListSubmissions) {
485
- const canList = await config.hooks.onBeforeListSubmissions(
486
- formId,
487
- context
487
+ await runHookWithShim(
488
+ () => config.hooks.onBeforeListSubmissions(formId, context),
489
+ ctx.error,
490
+ "Access denied"
488
491
  );
489
- if (!canList) {
490
- throw ctx.error(403, { message: "Access denied" });
491
- }
492
492
  }
493
493
  return getFormSubmissions(adapter, formId, { limit, offset });
494
494
  }
@@ -503,13 +503,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
503
503
  const { formId, subId } = ctx.params;
504
504
  const context = createContext(ctx.headers);
505
505
  if (config.hooks?.onBeforeGetSubmission) {
506
- const canGet = await config.hooks.onBeforeGetSubmission(
507
- subId,
508
- context
506
+ await runHookWithShim(
507
+ () => config.hooks.onBeforeGetSubmission(subId, context),
508
+ ctx.error,
509
+ "Access denied"
509
510
  );
510
- if (!canGet) {
511
- throw ctx.error(403, { message: "Access denied" });
512
- }
513
511
  }
514
512
  const submission = await adapter.findOne({
515
513
  model: "formSubmission",
@@ -539,13 +537,11 @@ const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
539
537
  throw ctx.error(404, { message: "Submission not found" });
540
538
  }
541
539
  if (config.hooks?.onBeforeSubmissionDeleted) {
542
- const canDelete = await config.hooks.onBeforeSubmissionDeleted(
543
- subId,
544
- context
540
+ await runHookWithShim(
541
+ () => config.hooks.onBeforeSubmissionDeleted(subId, context),
542
+ ctx.error,
543
+ "Delete operation denied"
545
544
  );
546
- if (!canDelete) {
547
- throw ctx.error(403, { message: "Delete operation denied" });
548
- }
549
545
  }
550
546
  await adapter.delete({
551
547
  model: "formSubmission",
@@ -34,10 +34,10 @@ function createFormListLoader(config) {
34
34
  };
35
35
  try {
36
36
  if (hooks?.beforeLoadFormList) {
37
- const canLoad = await hooks.beforeLoadFormList(context);
38
- if (!canLoad) {
39
- throw new Error("Load prevented by beforeLoadFormList hook");
40
- }
37
+ await client.runClientHookWithShim(
38
+ () => hooks.beforeLoadFormList(context),
39
+ "Load prevented by beforeLoadFormList hook"
40
+ );
41
41
  }
42
42
  const client$1 = client.createApiClient({
43
43
  baseURL: apiBaseURL,
@@ -96,10 +96,10 @@ function createFormBuilderLoader(id, config) {
96
96
  };
97
97
  try {
98
98
  if (hooks?.beforeLoadFormBuilder) {
99
- const canLoad = await hooks.beforeLoadFormBuilder(id, context);
100
- if (!canLoad) {
101
- throw new Error("Load prevented by beforeLoadFormBuilder hook");
102
- }
99
+ await client.runClientHookWithShim(
100
+ () => hooks.beforeLoadFormBuilder(id, context),
101
+ "Load prevented by beforeLoadFormBuilder hook"
102
+ );
103
103
  }
104
104
  const client$1 = client.createApiClient({
105
105
  baseURL: apiBaseURL,
@@ -148,10 +148,10 @@ function createSubmissionsLoader(formId, config) {
148
148
  };
149
149
  try {
150
150
  if (hooks?.beforeLoadSubmissions) {
151
- const canLoad = await hooks.beforeLoadSubmissions(formId, context);
152
- if (!canLoad) {
153
- throw new Error("Load prevented by beforeLoadSubmissions hook");
154
- }
151
+ await client.runClientHookWithShim(
152
+ () => hooks.beforeLoadSubmissions(formId, context),
153
+ "Load prevented by beforeLoadSubmissions hook"
154
+ );
155
155
  }
156
156
  const client$1 = client.createApiClient({
157
157
  baseURL: apiBaseURL,
@@ -1,6 +1,6 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { lazy } from 'react';
3
- import { defineClientPlugin, createApiClient, isConnectionError } from '@btst/stack/plugins/client';
3
+ import { defineClientPlugin, createApiClient, runClientHookWithShim, isConnectionError } from '@btst/stack/plugins/client';
4
4
  import { createRoute } from '@btst/yar';
5
5
  import { createFormBuilderQueryKeys } from '../../../../../../plugins/form-builder/query-keys.mjs';
6
6
 
@@ -32,10 +32,10 @@ function createFormListLoader(config) {
32
32
  };
33
33
  try {
34
34
  if (hooks?.beforeLoadFormList) {
35
- const canLoad = await hooks.beforeLoadFormList(context);
36
- if (!canLoad) {
37
- throw new Error("Load prevented by beforeLoadFormList hook");
38
- }
35
+ await runClientHookWithShim(
36
+ () => hooks.beforeLoadFormList(context),
37
+ "Load prevented by beforeLoadFormList hook"
38
+ );
39
39
  }
40
40
  const client = createApiClient({
41
41
  baseURL: apiBaseURL,
@@ -94,10 +94,10 @@ function createFormBuilderLoader(id, config) {
94
94
  };
95
95
  try {
96
96
  if (hooks?.beforeLoadFormBuilder) {
97
- const canLoad = await hooks.beforeLoadFormBuilder(id, context);
98
- if (!canLoad) {
99
- throw new Error("Load prevented by beforeLoadFormBuilder hook");
100
- }
97
+ await runClientHookWithShim(
98
+ () => hooks.beforeLoadFormBuilder(id, context),
99
+ "Load prevented by beforeLoadFormBuilder hook"
100
+ );
101
101
  }
102
102
  const client = createApiClient({
103
103
  baseURL: apiBaseURL,
@@ -146,10 +146,10 @@ function createSubmissionsLoader(formId, config) {
146
146
  };
147
147
  try {
148
148
  if (hooks?.beforeLoadSubmissions) {
149
- const canLoad = await hooks.beforeLoadSubmissions(formId, context);
150
- if (!canLoad) {
151
- throw new Error("Load prevented by beforeLoadSubmissions hook");
152
- }
149
+ await runClientHookWithShim(
150
+ () => hooks.beforeLoadSubmissions(formId, context),
151
+ "Load prevented by beforeLoadSubmissions hook"
152
+ );
153
153
  }
154
154
  const client = createApiClient({
155
155
  baseURL: apiBaseURL,
@@ -2,11 +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
8
  const mutations = require('./mutations.cjs');
9
9
  const queryKeyDefs = require('./query-key-defs.cjs');
10
+ const utils = require('../../utils.cjs');
10
11
  const serializers = require('./serializers.cjs');
11
12
 
12
13
  function createKanbanPrefetchForRoute(adapter) {
@@ -58,12 +59,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
58
59
  const context = { query, headers };
59
60
  try {
60
61
  if (hooks?.onBeforeListBoards) {
61
- const canList = await hooks.onBeforeListBoards(query, context);
62
- if (!canList) {
63
- throw ctx.error(403, {
64
- message: "Unauthorized: Cannot list boards"
65
- });
66
- }
62
+ await utils.runHookWithShim(
63
+ () => hooks.onBeforeListBoards(query, context),
64
+ ctx.error,
65
+ "Unauthorized: Cannot list boards"
66
+ );
67
67
  }
68
68
  const result = await getters.getAllBoards(adapter, query);
69
69
  if (hooks?.onBoardsRead) {
@@ -88,12 +88,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
88
88
  const context = { params, headers };
89
89
  try {
90
90
  if (hooks?.onBeforeReadBoard) {
91
- const canRead = await hooks.onBeforeReadBoard(params.id, context);
92
- if (!canRead) {
93
- throw ctx.error(403, {
94
- message: "Unauthorized: Cannot read board"
95
- });
96
- }
91
+ await utils.runHookWithShim(
92
+ () => hooks.onBeforeReadBoard(params.id, context),
93
+ ctx.error,
94
+ "Unauthorized: Cannot read board"
95
+ );
97
96
  }
98
97
  const result = await getters.getBoardById(adapter, params.id);
99
98
  if (!result) {
@@ -124,18 +123,14 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
124
123
  };
125
124
  try {
126
125
  if (hooks?.onBeforeCreateBoard) {
127
- const canCreate = await hooks.onBeforeCreateBoard(
128
- ctx.body,
129
- context
126
+ await utils.runHookWithShim(
127
+ () => hooks.onBeforeCreateBoard(ctx.body, context),
128
+ ctx.error,
129
+ "Unauthorized: Cannot create board"
130
130
  );
131
- if (!canCreate) {
132
- throw ctx.error(403, {
133
- message: "Unauthorized: Cannot create board"
134
- });
135
- }
136
131
  }
137
132
  const { ...boardData } = ctx.body;
138
- const slug = utils.slugify(boardData.slug || boardData.name);
133
+ const slug = utils$1.slugify(boardData.slug || boardData.name);
139
134
  if (!slug) {
140
135
  throw ctx.error(400, {
141
136
  message: "Invalid slug: must contain at least one alphanumeric character"
@@ -202,19 +197,18 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
202
197
  };
203
198
  try {
204
199
  if (hooks?.onBeforeUpdateBoard) {
205
- const canUpdate = await hooks.onBeforeUpdateBoard(
206
- ctx.params.id,
207
- { ...ctx.body, id: ctx.params.id },
208
- 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"
209
208
  );
210
- if (!canUpdate) {
211
- throw ctx.error(403, {
212
- message: "Unauthorized: Cannot update board"
213
- });
214
- }
215
209
  }
216
210
  const { slug: rawSlug, ...restBoardData } = ctx.body;
217
- const slugified = rawSlug ? utils.slugify(rawSlug) : void 0;
211
+ const slugified = rawSlug ? utils$1.slugify(rawSlug) : void 0;
218
212
  if (rawSlug && !slugified) {
219
213
  throw ctx.error(400, {
220
214
  message: "Invalid slug: must contain at least one alphanumeric character"
@@ -268,15 +262,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
268
262
  throw ctx.error(404, { message: "Board not found" });
269
263
  }
270
264
  if (hooks?.onBeforeDeleteBoard) {
271
- const canDelete = await hooks.onBeforeDeleteBoard(
272
- ctx.params.id,
273
- context
265
+ await utils.runHookWithShim(
266
+ () => hooks.onBeforeDeleteBoard(ctx.params.id, context),
267
+ ctx.error,
268
+ "Unauthorized: Cannot delete board"
274
269
  );
275
- if (!canDelete) {
276
- throw ctx.error(403, {
277
- message: "Unauthorized: Cannot delete board"
278
- });
279
- }
280
270
  }
281
271
  await adapter.delete({
282
272
  model: "kanbanBoard",
@@ -307,15 +297,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
307
297
  };
308
298
  try {
309
299
  if (hooks?.onBeforeCreateColumn) {
310
- const canCreate = await hooks.onBeforeCreateColumn(
311
- ctx.body,
312
- context
300
+ await utils.runHookWithShim(
301
+ () => hooks.onBeforeCreateColumn(ctx.body, context),
302
+ ctx.error,
303
+ "Unauthorized: Cannot create column"
313
304
  );
314
- if (!canCreate) {
315
- throw ctx.error(403, {
316
- message: "Unauthorized: Cannot create column"
317
- });
318
- }
319
305
  }
320
306
  const existingColumns = await adapter.findMany({
321
307
  model: "kanbanColumn",
@@ -360,16 +346,15 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
360
346
  };
361
347
  try {
362
348
  if (hooks?.onBeforeUpdateColumn) {
363
- const canUpdate = await hooks.onBeforeUpdateColumn(
364
- ctx.params.id,
365
- { ...ctx.body, id: ctx.params.id },
366
- 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"
367
357
  );
368
- if (!canUpdate) {
369
- throw ctx.error(403, {
370
- message: "Unauthorized: Cannot update column"
371
- });
372
- }
373
358
  }
374
359
  const updated = await adapter.update({
375
360
  model: "kanbanColumn",
@@ -412,15 +397,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
412
397
  throw ctx.error(404, { message: "Column not found" });
413
398
  }
414
399
  if (hooks?.onBeforeDeleteColumn) {
415
- const canDelete = await hooks.onBeforeDeleteColumn(
416
- ctx.params.id,
417
- context
400
+ await utils.runHookWithShim(
401
+ () => hooks.onBeforeDeleteColumn(ctx.params.id, context),
402
+ ctx.error,
403
+ "Unauthorized: Cannot delete column"
418
404
  );
419
- if (!canDelete) {
420
- throw ctx.error(403, {
421
- message: "Unauthorized: Cannot delete column"
422
- });
423
- }
424
405
  }
425
406
  await adapter.delete({
426
407
  model: "kanbanColumn",
@@ -451,16 +432,15 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
451
432
  for (let i = 0; i < columnIds.length; i++) {
452
433
  const columnId = columnIds[i];
453
434
  if (!columnId) continue;
454
- const canUpdate = await hooks.onBeforeUpdateColumn(
455
- columnId,
456
- { id: columnId, order: i },
457
- 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"
458
443
  );
459
- if (!canUpdate) {
460
- throw ctx.error(403, {
461
- message: "Unauthorized: Cannot reorder columns"
462
- });
463
- }
464
444
  }
465
445
  }
466
446
  const updatedColumns = [];
@@ -502,15 +482,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
502
482
  };
503
483
  try {
504
484
  if (hooks?.onBeforeCreateTask) {
505
- const canCreate = await hooks.onBeforeCreateTask(
506
- ctx.body,
507
- context
485
+ await utils.runHookWithShim(
486
+ () => hooks.onBeforeCreateTask(ctx.body, context),
487
+ ctx.error,
488
+ "Unauthorized: Cannot create task"
508
489
  );
509
- if (!canCreate) {
510
- throw ctx.error(403, {
511
- message: "Unauthorized: Cannot create task"
512
- });
513
- }
514
490
  }
515
491
  const existingTasks = await adapter.findMany({
516
492
  model: "kanbanTask",
@@ -561,16 +537,15 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
561
537
  };
562
538
  try {
563
539
  if (hooks?.onBeforeUpdateTask) {
564
- const canUpdate = await hooks.onBeforeUpdateTask(
565
- ctx.params.id,
566
- { ...ctx.body, id: ctx.params.id },
567
- 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"
568
548
  );
569
- if (!canUpdate) {
570
- throw ctx.error(403, {
571
- message: "Unauthorized: Cannot update task"
572
- });
573
- }
574
549
  }
575
550
  const updated = await adapter.update({
576
551
  model: "kanbanTask",
@@ -613,15 +588,11 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
613
588
  throw ctx.error(404, { message: "Task not found" });
614
589
  }
615
590
  if (hooks?.onBeforeDeleteTask) {
616
- const canDelete = await hooks.onBeforeDeleteTask(
617
- ctx.params.id,
618
- context
591
+ await utils.runHookWithShim(
592
+ () => hooks.onBeforeDeleteTask(ctx.params.id, context),
593
+ ctx.error,
594
+ "Unauthorized: Cannot delete task"
619
595
  );
620
- if (!canDelete) {
621
- throw ctx.error(403, {
622
- message: "Unauthorized: Cannot delete task"
623
- });
624
- }
625
596
  }
626
597
  await adapter.delete({
627
598
  model: "kanbanTask",
@@ -656,16 +627,15 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
656
627
  throw ctx.error(404, { message: "Task not found" });
657
628
  }
658
629
  if (hooks?.onBeforeUpdateTask) {
659
- const canUpdate = await hooks.onBeforeUpdateTask(
660
- taskId,
661
- { id: taskId, columnId: targetColumnId, order: targetOrder },
662
- 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"
663
638
  );
664
- if (!canUpdate) {
665
- throw ctx.error(403, {
666
- message: "Unauthorized: Cannot move task"
667
- });
668
- }
669
639
  }
670
640
  const updated = await adapter.update({
671
641
  model: "kanbanTask",
@@ -701,16 +671,15 @@ const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
701
671
  for (let i = 0; i < taskIds.length; i++) {
702
672
  const taskId = taskIds[i];
703
673
  if (!taskId) continue;
704
- const canUpdate = await hooks.onBeforeUpdateTask(
705
- taskId,
706
- { id: taskId, order: i },
707
- 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"
708
682
  );
709
- if (!canUpdate) {
710
- throw ctx.error(403, {
711
- message: "Unauthorized: Cannot reorder tasks"
712
- });
713
- }
714
683
  }
715
684
  }
716
685
  const updatedTasks = [];