@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
@@ -5,6 +5,7 @@ import { BoardListQuerySchema, createBoardSchema, updateBoardSchema, createColum
5
5
  import { getBoardById, getAllBoards } from './getters.mjs';
6
6
  import { getKanbanColumnsByBoardId, findOrCreateKanbanBoard, createKanbanTask } from './mutations.mjs';
7
7
  import { KANBAN_QUERY_KEYS } from './query-key-defs.mjs';
8
+ import { runHookWithShim } from '../../utils.mjs';
8
9
  import { serializeBoard } from './serializers.mjs';
9
10
 
10
11
  function createKanbanPrefetchForRoute(adapter) {
@@ -56,12 +57,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
56
57
  const context = { query, headers };
57
58
  try {
58
59
  if (hooks?.onBeforeListBoards) {
59
- const canList = await hooks.onBeforeListBoards(query, context);
60
- if (!canList) {
61
- throw ctx.error(403, {
62
- message: "Unauthorized: Cannot list boards"
63
- });
64
- }
60
+ await runHookWithShim(
61
+ () => hooks.onBeforeListBoards(query, context),
62
+ ctx.error,
63
+ "Unauthorized: Cannot list boards"
64
+ );
65
65
  }
66
66
  const result = await getAllBoards(adapter, query);
67
67
  if (hooks?.onBoardsRead) {
@@ -86,12 +86,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
86
86
  const context = { params, headers };
87
87
  try {
88
88
  if (hooks?.onBeforeReadBoard) {
89
- const canRead = await hooks.onBeforeReadBoard(params.id, context);
90
- if (!canRead) {
91
- throw ctx.error(403, {
92
- message: "Unauthorized: Cannot read board"
93
- });
94
- }
89
+ await runHookWithShim(
90
+ () => hooks.onBeforeReadBoard(params.id, context),
91
+ ctx.error,
92
+ "Unauthorized: Cannot read board"
93
+ );
95
94
  }
96
95
  const result = await getBoardById(adapter, params.id);
97
96
  if (!result) {
@@ -122,15 +121,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
122
121
  };
123
122
  try {
124
123
  if (hooks?.onBeforeCreateBoard) {
125
- const canCreate = await hooks.onBeforeCreateBoard(
126
- ctx.body,
127
- context
124
+ await runHookWithShim(
125
+ () => hooks.onBeforeCreateBoard(ctx.body, context),
126
+ ctx.error,
127
+ "Unauthorized: Cannot create board"
128
128
  );
129
- if (!canCreate) {
130
- throw ctx.error(403, {
131
- message: "Unauthorized: Cannot create board"
132
- });
133
- }
134
129
  }
135
130
  const { ...boardData } = ctx.body;
136
131
  const slug = slugify(boardData.slug || boardData.name);
@@ -200,16 +195,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
200
195
  };
201
196
  try {
202
197
  if (hooks?.onBeforeUpdateBoard) {
203
- const canUpdate = await hooks.onBeforeUpdateBoard(
204
- ctx.params.id,
205
- { ...ctx.body, id: ctx.params.id },
206
- 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"
207
206
  );
208
- if (!canUpdate) {
209
- throw ctx.error(403, {
210
- message: "Unauthorized: Cannot update board"
211
- });
212
- }
213
207
  }
214
208
  const { slug: rawSlug, ...restBoardData } = ctx.body;
215
209
  const slugified = rawSlug ? slugify(rawSlug) : void 0;
@@ -266,15 +260,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
266
260
  throw ctx.error(404, { message: "Board not found" });
267
261
  }
268
262
  if (hooks?.onBeforeDeleteBoard) {
269
- const canDelete = await hooks.onBeforeDeleteBoard(
270
- ctx.params.id,
271
- context
263
+ await runHookWithShim(
264
+ () => hooks.onBeforeDeleteBoard(ctx.params.id, context),
265
+ ctx.error,
266
+ "Unauthorized: Cannot delete board"
272
267
  );
273
- if (!canDelete) {
274
- throw ctx.error(403, {
275
- message: "Unauthorized: Cannot delete board"
276
- });
277
- }
278
268
  }
279
269
  await adapter.delete({
280
270
  model: "kanbanBoard",
@@ -305,15 +295,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
305
295
  };
306
296
  try {
307
297
  if (hooks?.onBeforeCreateColumn) {
308
- const canCreate = await hooks.onBeforeCreateColumn(
309
- ctx.body,
310
- context
298
+ await runHookWithShim(
299
+ () => hooks.onBeforeCreateColumn(ctx.body, context),
300
+ ctx.error,
301
+ "Unauthorized: Cannot create column"
311
302
  );
312
- if (!canCreate) {
313
- throw ctx.error(403, {
314
- message: "Unauthorized: Cannot create column"
315
- });
316
- }
317
303
  }
318
304
  const existingColumns = await adapter.findMany({
319
305
  model: "kanbanColumn",
@@ -358,16 +344,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
358
344
  };
359
345
  try {
360
346
  if (hooks?.onBeforeUpdateColumn) {
361
- const canUpdate = await hooks.onBeforeUpdateColumn(
362
- ctx.params.id,
363
- { ...ctx.body, id: ctx.params.id },
364
- 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"
365
355
  );
366
- if (!canUpdate) {
367
- throw ctx.error(403, {
368
- message: "Unauthorized: Cannot update column"
369
- });
370
- }
371
356
  }
372
357
  const updated = await adapter.update({
373
358
  model: "kanbanColumn",
@@ -410,15 +395,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
410
395
  throw ctx.error(404, { message: "Column not found" });
411
396
  }
412
397
  if (hooks?.onBeforeDeleteColumn) {
413
- const canDelete = await hooks.onBeforeDeleteColumn(
414
- ctx.params.id,
415
- context
398
+ await runHookWithShim(
399
+ () => hooks.onBeforeDeleteColumn(ctx.params.id, context),
400
+ ctx.error,
401
+ "Unauthorized: Cannot delete column"
416
402
  );
417
- if (!canDelete) {
418
- throw ctx.error(403, {
419
- message: "Unauthorized: Cannot delete column"
420
- });
421
- }
422
403
  }
423
404
  await adapter.delete({
424
405
  model: "kanbanColumn",
@@ -449,16 +430,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
449
430
  for (let i = 0; i < columnIds.length; i++) {
450
431
  const columnId = columnIds[i];
451
432
  if (!columnId) continue;
452
- const canUpdate = await hooks.onBeforeUpdateColumn(
453
- columnId,
454
- { id: columnId, order: i },
455
- 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"
456
441
  );
457
- if (!canUpdate) {
458
- throw ctx.error(403, {
459
- message: "Unauthorized: Cannot reorder columns"
460
- });
461
- }
462
442
  }
463
443
  }
464
444
  const updatedColumns = [];
@@ -500,15 +480,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
500
480
  };
501
481
  try {
502
482
  if (hooks?.onBeforeCreateTask) {
503
- const canCreate = await hooks.onBeforeCreateTask(
504
- ctx.body,
505
- context
483
+ await runHookWithShim(
484
+ () => hooks.onBeforeCreateTask(ctx.body, context),
485
+ ctx.error,
486
+ "Unauthorized: Cannot create task"
506
487
  );
507
- if (!canCreate) {
508
- throw ctx.error(403, {
509
- message: "Unauthorized: Cannot create task"
510
- });
511
- }
512
488
  }
513
489
  const existingTasks = await adapter.findMany({
514
490
  model: "kanbanTask",
@@ -559,16 +535,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
559
535
  };
560
536
  try {
561
537
  if (hooks?.onBeforeUpdateTask) {
562
- const canUpdate = await hooks.onBeforeUpdateTask(
563
- ctx.params.id,
564
- { ...ctx.body, id: ctx.params.id },
565
- 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"
566
546
  );
567
- if (!canUpdate) {
568
- throw ctx.error(403, {
569
- message: "Unauthorized: Cannot update task"
570
- });
571
- }
572
547
  }
573
548
  const updated = await adapter.update({
574
549
  model: "kanbanTask",
@@ -611,15 +586,11 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
611
586
  throw ctx.error(404, { message: "Task not found" });
612
587
  }
613
588
  if (hooks?.onBeforeDeleteTask) {
614
- const canDelete = await hooks.onBeforeDeleteTask(
615
- ctx.params.id,
616
- context
589
+ await runHookWithShim(
590
+ () => hooks.onBeforeDeleteTask(ctx.params.id, context),
591
+ ctx.error,
592
+ "Unauthorized: Cannot delete task"
617
593
  );
618
- if (!canDelete) {
619
- throw ctx.error(403, {
620
- message: "Unauthorized: Cannot delete task"
621
- });
622
- }
623
594
  }
624
595
  await adapter.delete({
625
596
  model: "kanbanTask",
@@ -654,16 +625,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
654
625
  throw ctx.error(404, { message: "Task not found" });
655
626
  }
656
627
  if (hooks?.onBeforeUpdateTask) {
657
- const canUpdate = await hooks.onBeforeUpdateTask(
658
- taskId,
659
- { id: taskId, columnId: targetColumnId, order: targetOrder },
660
- 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"
661
636
  );
662
- if (!canUpdate) {
663
- throw ctx.error(403, {
664
- message: "Unauthorized: Cannot move task"
665
- });
666
- }
667
637
  }
668
638
  const updated = await adapter.update({
669
639
  model: "kanbanTask",
@@ -699,16 +669,15 @@ const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
699
669
  for (let i = 0; i < taskIds.length; i++) {
700
670
  const taskId = taskIds[i];
701
671
  if (!taskId) continue;
702
- const canUpdate = await hooks.onBeforeUpdateTask(
703
- taskId,
704
- { id: taskId, order: i },
705
- 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"
706
680
  );
707
- if (!canUpdate) {
708
- throw ctx.error(403, {
709
- message: "Unauthorized: Cannot reorder tasks"
710
- });
711
- }
712
681
  }
713
682
  }
714
683
  const updatedTasks = [];
@@ -21,10 +21,10 @@ function createBoardsLoader(config) {
21
21
  };
22
22
  try {
23
23
  if (hooks?.beforeLoadBoards) {
24
- const canLoad = await hooks.beforeLoadBoards(context);
25
- if (!canLoad) {
26
- throw new Error("Load prevented by beforeLoadBoards hook");
27
- }
24
+ await client.runClientHookWithShim(
25
+ () => hooks.beforeLoadBoards(context),
26
+ "Load prevented by beforeLoadBoards hook"
27
+ );
28
28
  }
29
29
  const client$1 = client.createApiClient({
30
30
  baseURL: apiBaseURL,
@@ -37,13 +37,10 @@ function createBoardsLoader(config) {
37
37
  const boards = queryClient.getQueryData(
38
38
  listQuery.queryKey
39
39
  );
40
- const canContinue = await hooks.afterLoadBoards(
41
- boards || null,
42
- context
40
+ await client.runClientHookWithShim(
41
+ () => hooks.afterLoadBoards(boards || null, context),
42
+ "Load prevented by afterLoadBoards hook"
43
43
  );
44
- if (canContinue === false) {
45
- throw new Error("Load prevented by afterLoadBoards hook");
46
- }
47
44
  }
48
45
  const queryState = queryClient.getQueryState(listQuery.queryKey);
49
46
  if (queryState?.error && hooks?.onLoadError) {
@@ -77,10 +74,10 @@ function createBoardLoader(boardId, config) {
77
74
  };
78
75
  try {
79
76
  if (hooks?.beforeLoadBoard) {
80
- const canLoad = await hooks.beforeLoadBoard(boardId, context);
81
- if (!canLoad) {
82
- throw new Error("Load prevented by beforeLoadBoard hook");
83
- }
77
+ await client.runClientHookWithShim(
78
+ () => hooks.beforeLoadBoard(boardId, context),
79
+ "Load prevented by beforeLoadBoard hook"
80
+ );
84
81
  }
85
82
  const client$1 = client.createApiClient({
86
83
  baseURL: apiBaseURL,
@@ -93,14 +90,10 @@ function createBoardLoader(boardId, config) {
93
90
  const board = queryClient.getQueryData(
94
91
  boardQuery.queryKey
95
92
  );
96
- const canContinue = await hooks.afterLoadBoard(
97
- board || null,
98
- boardId,
99
- context
93
+ await client.runClientHookWithShim(
94
+ () => hooks.afterLoadBoard(board || null, boardId, context),
95
+ "Load prevented by afterLoadBoard hook"
100
96
  );
101
- if (canContinue === false) {
102
- throw new Error("Load prevented by afterLoadBoard hook");
103
- }
104
97
  }
105
98
  const queryState = queryClient.getQueryState(boardQuery.queryKey);
106
99
  if (queryState?.error && hooks?.onLoadError) {
@@ -133,16 +126,16 @@ function createNewBoardLoader(config) {
133
126
  };
134
127
  try {
135
128
  if (hooks?.beforeLoadNewBoard) {
136
- const canLoad = await hooks.beforeLoadNewBoard(context);
137
- if (!canLoad) {
138
- throw new Error("Load prevented by beforeLoadNewBoard hook");
139
- }
129
+ await client.runClientHookWithShim(
130
+ () => hooks.beforeLoadNewBoard(context),
131
+ "Load prevented by beforeLoadNewBoard hook"
132
+ );
140
133
  }
141
134
  if (hooks?.afterLoadNewBoard) {
142
- const canContinue = await hooks.afterLoadNewBoard(context);
143
- if (canContinue === false) {
144
- throw new Error("Load prevented by afterLoadNewBoard hook");
145
- }
135
+ await client.runClientHookWithShim(
136
+ () => hooks.afterLoadNewBoard(context),
137
+ "Load prevented by afterLoadNewBoard hook"
138
+ );
146
139
  }
147
140
  } catch (error) {
148
141
  if (hooks?.onLoadError) {
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { defineClientPlugin, createApiClient, isConnectionError } from '@btst/stack/plugins/client';
2
+ import { defineClientPlugin, createApiClient, runClientHookWithShim, isConnectionError } from '@btst/stack/plugins/client';
3
3
  import { createRoute } from '@btst/yar';
4
4
  import { createKanbanQueryKeys } from '../../../../../../plugins/kanban/query-keys.mjs';
5
5
  import { BoardsListPageComponent } from './components/pages/boards-list-page.mjs';
@@ -19,10 +19,10 @@ function createBoardsLoader(config) {
19
19
  };
20
20
  try {
21
21
  if (hooks?.beforeLoadBoards) {
22
- const canLoad = await hooks.beforeLoadBoards(context);
23
- if (!canLoad) {
24
- throw new Error("Load prevented by beforeLoadBoards hook");
25
- }
22
+ await runClientHookWithShim(
23
+ () => hooks.beforeLoadBoards(context),
24
+ "Load prevented by beforeLoadBoards hook"
25
+ );
26
26
  }
27
27
  const client = createApiClient({
28
28
  baseURL: apiBaseURL,
@@ -35,13 +35,10 @@ function createBoardsLoader(config) {
35
35
  const boards = queryClient.getQueryData(
36
36
  listQuery.queryKey
37
37
  );
38
- const canContinue = await hooks.afterLoadBoards(
39
- boards || null,
40
- context
38
+ await runClientHookWithShim(
39
+ () => hooks.afterLoadBoards(boards || null, context),
40
+ "Load prevented by afterLoadBoards hook"
41
41
  );
42
- if (canContinue === false) {
43
- throw new Error("Load prevented by afterLoadBoards hook");
44
- }
45
42
  }
46
43
  const queryState = queryClient.getQueryState(listQuery.queryKey);
47
44
  if (queryState?.error && hooks?.onLoadError) {
@@ -75,10 +72,10 @@ function createBoardLoader(boardId, config) {
75
72
  };
76
73
  try {
77
74
  if (hooks?.beforeLoadBoard) {
78
- const canLoad = await hooks.beforeLoadBoard(boardId, context);
79
- if (!canLoad) {
80
- throw new Error("Load prevented by beforeLoadBoard hook");
81
- }
75
+ await runClientHookWithShim(
76
+ () => hooks.beforeLoadBoard(boardId, context),
77
+ "Load prevented by beforeLoadBoard hook"
78
+ );
82
79
  }
83
80
  const client = createApiClient({
84
81
  baseURL: apiBaseURL,
@@ -91,14 +88,10 @@ function createBoardLoader(boardId, config) {
91
88
  const board = queryClient.getQueryData(
92
89
  boardQuery.queryKey
93
90
  );
94
- const canContinue = await hooks.afterLoadBoard(
95
- board || null,
96
- boardId,
97
- context
91
+ await runClientHookWithShim(
92
+ () => hooks.afterLoadBoard(board || null, boardId, context),
93
+ "Load prevented by afterLoadBoard hook"
98
94
  );
99
- if (canContinue === false) {
100
- throw new Error("Load prevented by afterLoadBoard hook");
101
- }
102
95
  }
103
96
  const queryState = queryClient.getQueryState(boardQuery.queryKey);
104
97
  if (queryState?.error && hooks?.onLoadError) {
@@ -131,16 +124,16 @@ function createNewBoardLoader(config) {
131
124
  };
132
125
  try {
133
126
  if (hooks?.beforeLoadNewBoard) {
134
- const canLoad = await hooks.beforeLoadNewBoard(context);
135
- if (!canLoad) {
136
- throw new Error("Load prevented by beforeLoadNewBoard hook");
137
- }
127
+ await runClientHookWithShim(
128
+ () => hooks.beforeLoadNewBoard(context),
129
+ "Load prevented by beforeLoadNewBoard hook"
130
+ );
138
131
  }
139
132
  if (hooks?.afterLoadNewBoard) {
140
- const canContinue = await hooks.afterLoadNewBoard(context);
141
- if (canContinue === false) {
142
- throw new Error("Load prevented by afterLoadNewBoard hook");
143
- }
133
+ await runClientHookWithShim(
134
+ () => hooks.afterLoadNewBoard(context),
135
+ "Load prevented by afterLoadNewBoard hook"
136
+ );
144
137
  }
145
138
  } catch (error) {
146
139
  if (hooks?.onLoadError) {
@@ -31,10 +31,10 @@ function createPageListLoader(config) {
31
31
  };
32
32
  try {
33
33
  if (hooks?.beforeLoadPageList) {
34
- const canLoad = await hooks.beforeLoadPageList(context);
35
- if (!canLoad) {
36
- throw new Error("Load prevented by beforeLoadPageList hook");
37
- }
34
+ await client.runClientHookWithShim(
35
+ () => hooks.beforeLoadPageList(context),
36
+ "Load prevented by beforeLoadPageList hook"
37
+ );
38
38
  }
39
39
  const client$1 = client.createApiClient({
40
40
  baseURL: apiBaseURL,
@@ -97,10 +97,10 @@ function createPageBuilderLoader(id, config) {
97
97
  };
98
98
  try {
99
99
  if (hooks?.beforeLoadPageBuilder) {
100
- const canLoad = await hooks.beforeLoadPageBuilder(id, context);
101
- if (!canLoad) {
102
- throw new Error("Load prevented by beforeLoadPageBuilder hook");
103
- }
100
+ await client.runClientHookWithShim(
101
+ () => hooks.beforeLoadPageBuilder(id, context),
102
+ "Load prevented by beforeLoadPageBuilder hook"
103
+ );
104
104
  }
105
105
  const client$1 = client.createApiClient({
106
106
  baseURL: apiBaseURL,
@@ -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, runClientHookWithShim } from '@btst/stack/plugins/client';
4
4
  import { createRoute } from '@btst/yar';
5
5
  import { createCMSQueryKeys } from '../../../../../../plugins/cms/query-keys.mjs';
6
6
  import { UI_BUILDER_TYPE_SLUG } from '../schemas.mjs';
@@ -29,10 +29,10 @@ function createPageListLoader(config) {
29
29
  };
30
30
  try {
31
31
  if (hooks?.beforeLoadPageList) {
32
- const canLoad = await hooks.beforeLoadPageList(context);
33
- if (!canLoad) {
34
- throw new Error("Load prevented by beforeLoadPageList hook");
35
- }
32
+ await runClientHookWithShim(
33
+ () => hooks.beforeLoadPageList(context),
34
+ "Load prevented by beforeLoadPageList hook"
35
+ );
36
36
  }
37
37
  const client = createApiClient({
38
38
  baseURL: apiBaseURL,
@@ -95,10 +95,10 @@ function createPageBuilderLoader(id, config) {
95
95
  };
96
96
  try {
97
97
  if (hooks?.beforeLoadPageBuilder) {
98
- const canLoad = await hooks.beforeLoadPageBuilder(id, context);
99
- if (!canLoad) {
100
- throw new Error("Load prevented by beforeLoadPageBuilder hook");
101
- }
98
+ await runClientHookWithShim(
99
+ () => hooks.beforeLoadPageBuilder(id, context),
100
+ "Load prevented by beforeLoadPageBuilder hook"
101
+ );
102
102
  }
103
103
  const client = createApiClient({
104
104
  baseURL: apiBaseURL,
@@ -2,6 +2,46 @@
2
2
 
3
3
  const client = require('better-call/client');
4
4
 
5
+ async function runHookWithShim(hookFn, createError, defaultMessage, errorStatus = 403) {
6
+ let result;
7
+ try {
8
+ result = await hookFn();
9
+ } catch (e) {
10
+ throw createError(errorStatus, {
11
+ message: e instanceof Error ? e.message : defaultMessage
12
+ });
13
+ }
14
+ if (typeof result === "boolean") {
15
+ if (process.env.NODE_ENV !== "production") {
16
+ console.warn(
17
+ `[btst] A lifecycle hook returned a boolean (${result}). Boolean returns are deprecated \u2014 throw an Error to deny access instead. IMPORTANT: any code path in this hook that falls through to undefined now ALLOWS access (previously denied). Update the hook to throw new Error("Unauthorized") to deny.`
18
+ );
19
+ }
20
+ if (!result) {
21
+ throw createError(errorStatus, { message: defaultMessage });
22
+ }
23
+ }
24
+ return result;
25
+ }
26
+ async function runClientHookWithShim(hookFn, defaultMessage) {
27
+ let result;
28
+ try {
29
+ result = await hookFn();
30
+ } catch (e) {
31
+ throw e instanceof Error ? e : new Error(defaultMessage);
32
+ }
33
+ if (typeof result === "boolean") {
34
+ if (process.env.NODE_ENV !== "production") {
35
+ console.warn(
36
+ `[btst] A lifecycle hook returned a boolean (${result}). Boolean returns are deprecated \u2014 throw an Error to deny access instead. IMPORTANT: any code path in this hook that falls through to undefined now ALLOWS access (previously denied). Update the hook to throw new Error("Unauthorized") to deny.`
37
+ );
38
+ }
39
+ if (!result) {
40
+ throw new Error(defaultMessage);
41
+ }
42
+ }
43
+ return result;
44
+ }
5
45
  function isConnectionError(err) {
6
46
  if (!(err instanceof Error)) return false;
7
47
  const code = err.cause?.code ?? err.code;
@@ -20,3 +60,5 @@ function createApiClient(options) {
20
60
 
21
61
  exports.createApiClient = createApiClient;
22
62
  exports.isConnectionError = isConnectionError;
63
+ exports.runClientHookWithShim = runClientHookWithShim;
64
+ exports.runHookWithShim = runHookWithShim;
@@ -1,5 +1,45 @@
1
1
  import { createClient } from 'better-call/client';
2
2
 
3
+ async function runHookWithShim(hookFn, createError, defaultMessage, errorStatus = 403) {
4
+ let result;
5
+ try {
6
+ result = await hookFn();
7
+ } catch (e) {
8
+ throw createError(errorStatus, {
9
+ message: e instanceof Error ? e.message : defaultMessage
10
+ });
11
+ }
12
+ if (typeof result === "boolean") {
13
+ if (process.env.NODE_ENV !== "production") {
14
+ console.warn(
15
+ `[btst] A lifecycle hook returned a boolean (${result}). Boolean returns are deprecated \u2014 throw an Error to deny access instead. IMPORTANT: any code path in this hook that falls through to undefined now ALLOWS access (previously denied). Update the hook to throw new Error("Unauthorized") to deny.`
16
+ );
17
+ }
18
+ if (!result) {
19
+ throw createError(errorStatus, { message: defaultMessage });
20
+ }
21
+ }
22
+ return result;
23
+ }
24
+ async function runClientHookWithShim(hookFn, defaultMessage) {
25
+ let result;
26
+ try {
27
+ result = await hookFn();
28
+ } catch (e) {
29
+ throw e instanceof Error ? e : new Error(defaultMessage);
30
+ }
31
+ if (typeof result === "boolean") {
32
+ if (process.env.NODE_ENV !== "production") {
33
+ console.warn(
34
+ `[btst] A lifecycle hook returned a boolean (${result}). Boolean returns are deprecated \u2014 throw an Error to deny access instead. IMPORTANT: any code path in this hook that falls through to undefined now ALLOWS access (previously denied). Update the hook to throw new Error("Unauthorized") to deny.`
35
+ );
36
+ }
37
+ if (!result) {
38
+ throw new Error(defaultMessage);
39
+ }
40
+ }
41
+ return result;
42
+ }
3
43
  function isConnectionError(err) {
4
44
  if (!(err instanceof Error)) return false;
5
45
  const code = err.cause?.code ?? err.code;
@@ -16,4 +56,4 @@ function createApiClient(options) {
16
56
  });
17
57
  }
18
58
 
19
- export { createApiClient, isConnectionError };
59
+ export { createApiClient, isConnectionError, runClientHookWithShim, runHookWithShim };