@btst/stack 2.2.0 → 2.3.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 (159) hide show
  1. package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +52 -1
  2. package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +52 -1
  3. package/dist/packages/stack/src/plugins/blog/api/query-key-defs.cjs +18 -0
  4. package/dist/packages/stack/src/plugins/blog/api/query-key-defs.mjs +15 -0
  5. package/dist/packages/stack/src/plugins/blog/api/serializers.cjs +21 -0
  6. package/dist/packages/stack/src/plugins/blog/api/serializers.mjs +18 -0
  7. package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +15 -0
  8. package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +16 -1
  9. package/dist/packages/stack/src/plugins/cms/api/getters.cjs +10 -0
  10. package/dist/packages/stack/src/plugins/cms/api/getters.mjs +10 -1
  11. package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +70 -1
  12. package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +71 -2
  13. package/dist/packages/stack/src/plugins/cms/api/query-key-defs.cjs +29 -0
  14. package/dist/packages/stack/src/plugins/cms/api/query-key-defs.mjs +26 -0
  15. package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +15 -0
  16. package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +16 -1
  17. package/dist/packages/stack/src/plugins/form-builder/api/getters.cjs +9 -0
  18. package/dist/packages/stack/src/plugins/form-builder/api/getters.mjs +9 -1
  19. package/dist/packages/stack/src/plugins/form-builder/api/plugin.cjs +62 -1
  20. package/dist/packages/stack/src/plugins/form-builder/api/plugin.mjs +63 -2
  21. package/dist/packages/stack/src/plugins/form-builder/api/query-key-defs.cjs +37 -0
  22. package/dist/packages/stack/src/plugins/form-builder/api/query-key-defs.mjs +33 -0
  23. package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +15 -0
  24. package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +16 -1
  25. package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +29 -1
  26. package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +29 -1
  27. package/dist/packages/stack/src/plugins/kanban/api/query-key-defs.cjs +26 -0
  28. package/dist/packages/stack/src/plugins/kanban/api/query-key-defs.mjs +23 -0
  29. package/dist/packages/stack/src/plugins/kanban/api/serializers.cjs +30 -0
  30. package/dist/packages/stack/src/plugins/kanban/api/serializers.mjs +26 -0
  31. package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +10 -0
  32. package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +11 -1
  33. package/dist/packages/stack/src/plugins/utils.cjs +6 -0
  34. package/dist/packages/stack/src/plugins/utils.mjs +6 -1
  35. package/dist/plugins/blog/api/index.cjs +5 -0
  36. package/dist/plugins/blog/api/index.d.cts +19 -4
  37. package/dist/plugins/blog/api/index.d.mts +19 -4
  38. package/dist/plugins/blog/api/index.d.ts +19 -4
  39. package/dist/plugins/blog/api/index.mjs +2 -0
  40. package/dist/plugins/blog/client/hooks/index.d.cts +4 -4
  41. package/dist/plugins/blog/client/hooks/index.d.mts +4 -4
  42. package/dist/plugins/blog/client/hooks/index.d.ts +4 -4
  43. package/dist/plugins/blog/client/index.d.cts +1 -1
  44. package/dist/plugins/blog/client/index.d.mts +1 -1
  45. package/dist/plugins/blog/client/index.d.ts +1 -1
  46. package/dist/plugins/blog/query-keys.cjs +6 -5
  47. package/dist/plugins/blog/query-keys.d.cts +8 -387
  48. package/dist/plugins/blog/query-keys.d.mts +8 -387
  49. package/dist/plugins/blog/query-keys.d.ts +8 -387
  50. package/dist/plugins/blog/query-keys.mjs +6 -5
  51. package/dist/plugins/client/index.cjs +1 -0
  52. package/dist/plugins/client/index.d.cts +8 -1
  53. package/dist/plugins/client/index.d.mts +8 -1
  54. package/dist/plugins/client/index.d.ts +8 -1
  55. package/dist/plugins/client/index.mjs +1 -1
  56. package/dist/plugins/cms/api/index.cjs +6 -0
  57. package/dist/plugins/cms/api/index.d.cts +7 -219
  58. package/dist/plugins/cms/api/index.d.mts +7 -219
  59. package/dist/plugins/cms/api/index.d.ts +7 -219
  60. package/dist/plugins/cms/api/index.mjs +2 -1
  61. package/dist/plugins/cms/client/hooks/index.d.cts +1 -1
  62. package/dist/plugins/cms/client/hooks/index.d.mts +1 -1
  63. package/dist/plugins/cms/client/hooks/index.d.ts +1 -1
  64. package/dist/plugins/cms/query-keys.cjs +2 -1
  65. package/dist/plugins/cms/query-keys.d.cts +5 -9
  66. package/dist/plugins/cms/query-keys.d.mts +5 -9
  67. package/dist/plugins/cms/query-keys.d.ts +5 -9
  68. package/dist/plugins/cms/query-keys.mjs +2 -1
  69. package/dist/plugins/form-builder/api/index.cjs +6 -0
  70. package/dist/plugins/form-builder/api/index.d.cts +7 -211
  71. package/dist/plugins/form-builder/api/index.d.mts +7 -211
  72. package/dist/plugins/form-builder/api/index.d.ts +7 -211
  73. package/dist/plugins/form-builder/api/index.mjs +2 -1
  74. package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
  75. package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
  76. package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
  77. package/dist/plugins/form-builder/client/hooks/index.d.cts +1 -1
  78. package/dist/plugins/form-builder/client/hooks/index.d.mts +1 -1
  79. package/dist/plugins/form-builder/client/hooks/index.d.ts +1 -1
  80. package/dist/plugins/form-builder/query-keys.cjs +3 -2
  81. package/dist/plugins/form-builder/query-keys.d.cts +6 -6
  82. package/dist/plugins/form-builder/query-keys.d.mts +6 -6
  83. package/dist/plugins/form-builder/query-keys.d.ts +6 -6
  84. package/dist/plugins/form-builder/query-keys.mjs +3 -2
  85. package/dist/plugins/kanban/api/index.cjs +6 -0
  86. package/dist/plugins/kanban/api/index.d.cts +17 -392
  87. package/dist/plugins/kanban/api/index.d.mts +17 -392
  88. package/dist/plugins/kanban/api/index.d.ts +17 -392
  89. package/dist/plugins/kanban/api/index.mjs +2 -0
  90. package/dist/plugins/kanban/client/components/index.d.cts +1 -1
  91. package/dist/plugins/kanban/client/components/index.d.mts +1 -1
  92. package/dist/plugins/kanban/client/components/index.d.ts +1 -1
  93. package/dist/plugins/kanban/client/hooks/index.d.cts +1 -1
  94. package/dist/plugins/kanban/client/hooks/index.d.mts +1 -1
  95. package/dist/plugins/kanban/client/hooks/index.d.ts +1 -1
  96. package/dist/plugins/kanban/client/index.d.cts +1 -1
  97. package/dist/plugins/kanban/client/index.d.mts +1 -1
  98. package/dist/plugins/kanban/client/index.d.ts +1 -1
  99. package/dist/plugins/kanban/query-keys.cjs +2 -9
  100. package/dist/plugins/kanban/query-keys.d.cts +4 -16
  101. package/dist/plugins/kanban/query-keys.d.mts +4 -16
  102. package/dist/plugins/kanban/query-keys.d.ts +4 -16
  103. package/dist/plugins/kanban/query-keys.mjs +2 -9
  104. package/dist/plugins/ui-builder/index.d.cts +1 -1
  105. package/dist/plugins/ui-builder/index.d.mts +1 -1
  106. package/dist/plugins/ui-builder/index.d.ts +1 -1
  107. package/dist/shared/stack.B1EeBt1b.d.ts +297 -0
  108. package/dist/shared/stack.BIXEI6v_.d.mts +419 -0
  109. package/dist/shared/stack.BKfolAyK.d.ts +419 -0
  110. package/dist/shared/stack.BpolpQpf.d.cts +445 -0
  111. package/dist/shared/stack.C5dtIncc.d.mts +293 -0
  112. package/dist/shared/stack.CIP6QS9l.d.ts +293 -0
  113. package/dist/shared/stack.CP68pFEH.d.mts +297 -0
  114. package/dist/shared/{stack.CXjzTMsb.d.mts → stack.CVDTkMoO.d.cts} +7 -1
  115. package/dist/shared/{stack.CXjzTMsb.d.ts → stack.CVDTkMoO.d.mts} +7 -1
  116. package/dist/shared/{stack.CXjzTMsb.d.cts → stack.CVDTkMoO.d.ts} +7 -1
  117. package/dist/shared/{stack.QD1y_7NY.d.mts → stack.DJaKVY7v.d.cts} +1 -1
  118. package/dist/shared/{stack.QD1y_7NY.d.ts → stack.DJaKVY7v.d.mts} +1 -1
  119. package/dist/shared/{stack.QD1y_7NY.d.cts → stack.DJaKVY7v.d.ts} +1 -1
  120. package/dist/shared/{stack.CIrIsc-A.d.mts → stack.DdI5W6MB.d.cts} +7 -1
  121. package/dist/shared/{stack.CIrIsc-A.d.ts → stack.DdI5W6MB.d.mts} +7 -1
  122. package/dist/shared/{stack.CIrIsc-A.d.cts → stack.DdI5W6MB.d.ts} +7 -1
  123. package/dist/shared/stack.Dw0Ly2TM.d.cts +293 -0
  124. package/dist/shared/stack.IdtKDRka.d.cts +297 -0
  125. package/dist/shared/stack.TIBF2AOx.d.ts +445 -0
  126. package/dist/shared/stack.rTy7-wQU.d.mts +445 -0
  127. package/dist/shared/stack.snB1EDP7.d.cts +419 -0
  128. package/package.json +3 -3
  129. package/src/plugins/blog/api/index.ts +2 -0
  130. package/src/plugins/blog/api/plugin.ts +85 -0
  131. package/src/plugins/blog/api/query-key-defs.ts +46 -0
  132. package/src/plugins/blog/api/serializers.ts +27 -0
  133. package/src/plugins/blog/client/plugin.tsx +19 -0
  134. package/src/plugins/blog/query-keys.ts +5 -7
  135. package/src/plugins/client/index.ts +1 -1
  136. package/src/plugins/cms/api/getters.ts +24 -0
  137. package/src/plugins/cms/api/index.ts +10 -1
  138. package/src/plugins/cms/api/plugin.ts +105 -0
  139. package/src/plugins/cms/api/query-key-defs.ts +53 -0
  140. package/src/plugins/cms/api/serializers.ts +12 -0
  141. package/src/plugins/cms/client/plugin.tsx +19 -0
  142. package/src/plugins/cms/query-keys.ts +2 -1
  143. package/src/plugins/form-builder/api/getters.ts +23 -0
  144. package/src/plugins/form-builder/api/index.ts +15 -2
  145. package/src/plugins/form-builder/api/plugin.ts +91 -0
  146. package/src/plugins/form-builder/api/query-key-defs.ts +79 -0
  147. package/src/plugins/form-builder/api/serializers.ts +12 -0
  148. package/src/plugins/form-builder/client/plugin.tsx +19 -0
  149. package/src/plugins/form-builder/query-keys.ts +6 -2
  150. package/src/plugins/kanban/api/index.ts +3 -0
  151. package/src/plugins/kanban/api/plugin.ts +49 -0
  152. package/src/plugins/kanban/api/query-key-defs.ts +54 -0
  153. package/src/plugins/kanban/api/serializers.ts +49 -0
  154. package/src/plugins/kanban/client/plugin.tsx +13 -0
  155. package/src/plugins/kanban/query-keys.ts +2 -9
  156. package/src/plugins/utils.ts +19 -0
  157. package/dist/shared/{stack.BkYlUT_8.d.cts → stack.CBON0dWL.d.cts} +6 -6
  158. package/dist/shared/{stack.BkYlUT_8.d.mts → stack.CBON0dWL.d.mts} +6 -6
  159. package/dist/shared/{stack.BkYlUT_8.d.ts → stack.CBON0dWL.d.ts} +6 -6
@@ -60,6 +60,14 @@ async function getAllForms(adapter, params) {
60
60
  offset: params?.offset
61
61
  };
62
62
  }
63
+ async function getFormById(adapter, id) {
64
+ const form = await adapter.findOne({
65
+ model: "form",
66
+ where: [{ field: "id", value: id, operator: "eq" }]
67
+ });
68
+ if (!form) return null;
69
+ return serializeForm(form);
70
+ }
63
71
  async function getFormBySlug(adapter, slug) {
64
72
  const form = await adapter.findOne({
65
73
  model: "form",
@@ -104,6 +112,7 @@ async function getFormSubmissions(adapter, formId, params) {
104
112
  }
105
113
 
106
114
  exports.getAllForms = getAllForms;
115
+ exports.getFormById = getFormById;
107
116
  exports.getFormBySlug = getFormBySlug;
108
117
  exports.getFormSubmissions = getFormSubmissions;
109
118
  exports.serializeForm = serializeForm;
@@ -58,6 +58,14 @@ async function getAllForms(adapter, params) {
58
58
  offset: params?.offset
59
59
  };
60
60
  }
61
+ async function getFormById(adapter, id) {
62
+ const form = await adapter.findOne({
63
+ model: "form",
64
+ where: [{ field: "id", value: id, operator: "eq" }]
65
+ });
66
+ if (!form) return null;
67
+ return serializeForm(form);
68
+ }
61
69
  async function getFormBySlug(adapter, slug) {
62
70
  const form = await adapter.findOne({
63
71
  model: "form",
@@ -101,4 +109,4 @@ async function getFormSubmissions(adapter, formId, params) {
101
109
  };
102
110
  }
103
111
 
104
- export { getAllForms, getFormBySlug, getFormSubmissions, serializeForm, serializeFormSubmission, serializeFormSubmissionWithData };
112
+ export { getAllForms, getFormById, getFormBySlug, getFormSubmissions, serializeForm, serializeFormSubmission, serializeFormSubmissionWithData };
@@ -7,14 +7,75 @@ const db = require('../db.cjs');
7
7
  const schemas = require('../schemas.cjs');
8
8
  const utils = require('../utils.cjs');
9
9
  const getters = require('./getters.cjs');
10
+ const queryKeyDefs = require('./query-key-defs.cjs');
10
11
 
12
+ function createFormBuilderPrefetchForRoute(adapter) {
13
+ return async function prefetchForRoute(key, qc, params) {
14
+ switch (key) {
15
+ case "formList": {
16
+ const result = await getters.getAllForms(adapter, { limit: 20, offset: 0 });
17
+ qc.setQueryData(queryKeyDefs.FORM_QUERY_KEYS.formsList({ limit: 20, offset: 0 }), {
18
+ pages: [
19
+ {
20
+ items: result.items,
21
+ total: result.total,
22
+ limit: result.limit ?? 20,
23
+ offset: result.offset ?? 0
24
+ }
25
+ ],
26
+ pageParams: [0]
27
+ });
28
+ break;
29
+ }
30
+ case "editForm": {
31
+ const id = params?.id ?? "";
32
+ if (id) {
33
+ const form = await getters.getFormById(adapter, id);
34
+ qc.setQueryData(queryKeyDefs.FORM_QUERY_KEYS.formById(id), form);
35
+ }
36
+ break;
37
+ }
38
+ case "submissions": {
39
+ const id = params?.id ?? "";
40
+ if (id) {
41
+ const [form, submissionsResult] = await Promise.all([
42
+ getters.getFormById(adapter, id),
43
+ getters.getFormSubmissions(adapter, id, { limit: 20, offset: 0 })
44
+ ]);
45
+ qc.setQueryData(queryKeyDefs.FORM_QUERY_KEYS.formById(id), form);
46
+ qc.setQueryData(
47
+ queryKeyDefs.FORM_QUERY_KEYS.submissionsList({
48
+ formId: id,
49
+ limit: 20,
50
+ offset: 0
51
+ }),
52
+ {
53
+ pages: [
54
+ {
55
+ items: submissionsResult.items,
56
+ total: submissionsResult.total,
57
+ limit: submissionsResult.limit ?? 20,
58
+ offset: submissionsResult.offset ?? 0
59
+ }
60
+ ],
61
+ pageParams: [0]
62
+ }
63
+ );
64
+ }
65
+ break;
66
+ }
67
+ }
68
+ };
69
+ }
11
70
  const formBuilderBackendPlugin = (config = {}) => api.defineBackendPlugin({
12
71
  name: "form-builder",
13
72
  dbPlugin: db.formBuilderSchema,
14
73
  api: (adapter) => ({
15
74
  getAllForms: (params) => getters.getAllForms(adapter, params),
75
+ getFormById: (id) => getters.getFormById(adapter, id),
16
76
  getFormBySlug: (slug) => getters.getFormBySlug(adapter, slug),
17
- getFormSubmissions: (formId, params) => getters.getFormSubmissions(adapter, formId, params)
77
+ getFormSubmissions: (formId, params) => getters.getFormSubmissions(adapter, formId, params),
78
+ prefetchForRoute: createFormBuilderPrefetchForRoute(adapter)
18
79
  }),
19
80
  routes: (adapter) => {
20
81
  const createContext = (headers) => ({
@@ -4,15 +4,76 @@ import { formSchemaToZod } from '../../../../../ui/src/lib/schema-converter.mjs'
4
4
  import { formBuilderSchema } from '../db.mjs';
5
5
  import { listFormsQuerySchema, createFormSchema, updateFormSchema, listSubmissionsQuerySchema } from '../schemas.mjs';
6
6
  import { extractUserAgent, extractIpAddress, slugify } from '../utils.mjs';
7
- import { getFormSubmissions, getFormBySlug, getAllForms, serializeForm, serializeFormSubmission, serializeFormSubmissionWithData } from './getters.mjs';
7
+ import { getFormSubmissions, getFormBySlug, getFormById, getAllForms, serializeForm, serializeFormSubmission, serializeFormSubmissionWithData } from './getters.mjs';
8
+ import { FORM_QUERY_KEYS } from './query-key-defs.mjs';
8
9
 
10
+ function createFormBuilderPrefetchForRoute(adapter) {
11
+ return async function prefetchForRoute(key, qc, params) {
12
+ switch (key) {
13
+ case "formList": {
14
+ const result = await getAllForms(adapter, { limit: 20, offset: 0 });
15
+ qc.setQueryData(FORM_QUERY_KEYS.formsList({ limit: 20, offset: 0 }), {
16
+ pages: [
17
+ {
18
+ items: result.items,
19
+ total: result.total,
20
+ limit: result.limit ?? 20,
21
+ offset: result.offset ?? 0
22
+ }
23
+ ],
24
+ pageParams: [0]
25
+ });
26
+ break;
27
+ }
28
+ case "editForm": {
29
+ const id = params?.id ?? "";
30
+ if (id) {
31
+ const form = await getFormById(adapter, id);
32
+ qc.setQueryData(FORM_QUERY_KEYS.formById(id), form);
33
+ }
34
+ break;
35
+ }
36
+ case "submissions": {
37
+ const id = params?.id ?? "";
38
+ if (id) {
39
+ const [form, submissionsResult] = await Promise.all([
40
+ getFormById(adapter, id),
41
+ getFormSubmissions(adapter, id, { limit: 20, offset: 0 })
42
+ ]);
43
+ qc.setQueryData(FORM_QUERY_KEYS.formById(id), form);
44
+ qc.setQueryData(
45
+ FORM_QUERY_KEYS.submissionsList({
46
+ formId: id,
47
+ limit: 20,
48
+ offset: 0
49
+ }),
50
+ {
51
+ pages: [
52
+ {
53
+ items: submissionsResult.items,
54
+ total: submissionsResult.total,
55
+ limit: submissionsResult.limit ?? 20,
56
+ offset: submissionsResult.offset ?? 0
57
+ }
58
+ ],
59
+ pageParams: [0]
60
+ }
61
+ );
62
+ }
63
+ break;
64
+ }
65
+ }
66
+ };
67
+ }
9
68
  const formBuilderBackendPlugin = (config = {}) => defineBackendPlugin({
10
69
  name: "form-builder",
11
70
  dbPlugin: formBuilderSchema,
12
71
  api: (adapter) => ({
13
72
  getAllForms: (params) => getAllForms(adapter, params),
73
+ getFormById: (id) => getFormById(adapter, id),
14
74
  getFormBySlug: (slug) => getFormBySlug(adapter, slug),
15
- getFormSubmissions: (formId, params) => getFormSubmissions(adapter, formId, params)
75
+ getFormSubmissions: (formId, params) => getFormSubmissions(adapter, formId, params),
76
+ prefetchForRoute: createFormBuilderPrefetchForRoute(adapter)
16
77
  }),
17
78
  routes: (adapter) => {
18
79
  const createContext = (headers) => ({
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ function formsListDiscriminator(params) {
4
+ return {
5
+ status: params?.status,
6
+ limit: params?.limit ?? 20,
7
+ offset: params?.offset ?? 0
8
+ };
9
+ }
10
+ function submissionsListDiscriminator(params) {
11
+ return {
12
+ formId: params.formId,
13
+ limit: params.limit ?? 20,
14
+ offset: params.offset ?? 0
15
+ };
16
+ }
17
+ const FORM_QUERY_KEYS = {
18
+ /**
19
+ * Key for forms.list(params) query.
20
+ * Full key: ["forms", "list", "list", { status, limit, offset }]
21
+ */
22
+ formsList: (params) => ["forms", "list", "list", formsListDiscriminator(params)],
23
+ /**
24
+ * Key for forms.byId(id) query.
25
+ * Full key: ["forms", "byId", "byId", id]
26
+ */
27
+ formById: (id) => ["forms", "byId", "byId", id],
28
+ /**
29
+ * Key for formSubmissions.list(params) query.
30
+ * Full key: ["formSubmissions", "list", { formId, limit, offset }]
31
+ */
32
+ submissionsList: (params) => ["formSubmissions", "list", submissionsListDiscriminator(params)]
33
+ };
34
+
35
+ exports.FORM_QUERY_KEYS = FORM_QUERY_KEYS;
36
+ exports.formsListDiscriminator = formsListDiscriminator;
37
+ exports.submissionsListDiscriminator = submissionsListDiscriminator;
@@ -0,0 +1,33 @@
1
+ function formsListDiscriminator(params) {
2
+ return {
3
+ status: params?.status,
4
+ limit: params?.limit ?? 20,
5
+ offset: params?.offset ?? 0
6
+ };
7
+ }
8
+ function submissionsListDiscriminator(params) {
9
+ return {
10
+ formId: params.formId,
11
+ limit: params.limit ?? 20,
12
+ offset: params.offset ?? 0
13
+ };
14
+ }
15
+ const FORM_QUERY_KEYS = {
16
+ /**
17
+ * Key for forms.list(params) query.
18
+ * Full key: ["forms", "list", "list", { status, limit, offset }]
19
+ */
20
+ formsList: (params) => ["forms", "list", "list", formsListDiscriminator(params)],
21
+ /**
22
+ * Key for forms.byId(id) query.
23
+ * Full key: ["forms", "byId", "byId", id]
24
+ */
25
+ formById: (id) => ["forms", "byId", "byId", id],
26
+ /**
27
+ * Key for formSubmissions.list(params) query.
28
+ * Full key: ["formSubmissions", "list", { formId, limit, offset }]
29
+ */
30
+ submissionsList: (params) => ["formSubmissions", "list", submissionsListDiscriminator(params)]
31
+ };
32
+
33
+ export { FORM_QUERY_KEYS, formsListDiscriminator, submissionsListDiscriminator };
@@ -70,6 +70,11 @@ function createFormListLoader(config) {
70
70
  await hooks.onLoadError(error, context);
71
71
  }
72
72
  } catch (error) {
73
+ if (client.isConnectionError(error)) {
74
+ console.warn(
75
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
76
+ );
77
+ }
73
78
  if (hooks?.onLoadError) {
74
79
  await hooks.onLoadError(error, context);
75
80
  }
@@ -117,6 +122,11 @@ function createFormBuilderLoader(id, config) {
117
122
  }
118
123
  }
119
124
  } catch (error) {
125
+ if (client.isConnectionError(error)) {
126
+ console.warn(
127
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
128
+ );
129
+ }
120
130
  if (hooks?.onLoadError) {
121
131
  await hooks.onLoadError(error, context);
122
132
  }
@@ -189,6 +199,11 @@ function createSubmissionsLoader(formId, config) {
189
199
  await hooks.onLoadError(error, context);
190
200
  }
191
201
  } catch (error) {
202
+ if (client.isConnectionError(error)) {
203
+ console.warn(
204
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
205
+ );
206
+ }
192
207
  if (hooks?.onLoadError) {
193
208
  await hooks.onLoadError(error, context);
194
209
  }
@@ -1,6 +1,6 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
2
  import { lazy } from 'react';
3
- import { defineClientPlugin, createApiClient } from '@btst/stack/plugins/client';
3
+ import { defineClientPlugin, createApiClient, isConnectionError } from '@btst/stack/plugins/client';
4
4
  import { createRoute } from '@btst/yar';
5
5
  import { createFormBuilderQueryKeys } from '../../../../../../plugins/form-builder/query-keys.mjs';
6
6
 
@@ -68,6 +68,11 @@ function createFormListLoader(config) {
68
68
  await hooks.onLoadError(error, context);
69
69
  }
70
70
  } catch (error) {
71
+ if (isConnectionError(error)) {
72
+ console.warn(
73
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
74
+ );
75
+ }
71
76
  if (hooks?.onLoadError) {
72
77
  await hooks.onLoadError(error, context);
73
78
  }
@@ -115,6 +120,11 @@ function createFormBuilderLoader(id, config) {
115
120
  }
116
121
  }
117
122
  } catch (error) {
123
+ if (isConnectionError(error)) {
124
+ console.warn(
125
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
126
+ );
127
+ }
118
128
  if (hooks?.onLoadError) {
119
129
  await hooks.onLoadError(error, context);
120
130
  }
@@ -187,6 +197,11 @@ function createSubmissionsLoader(formId, config) {
187
197
  await hooks.onLoadError(error, context);
188
198
  }
189
199
  } catch (error) {
200
+ if (isConnectionError(error)) {
201
+ console.warn(
202
+ "[btst/form-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.formBuilder.prefetchForRoute() for SSG data prefetching."
203
+ );
204
+ }
190
205
  if (hooks?.onLoadError) {
191
206
  await hooks.onLoadError(error, context);
192
207
  }
@@ -5,13 +5,41 @@ const db = require('../db.cjs');
5
5
  const utils = require('../utils.cjs');
6
6
  const schemas = require('../schemas.cjs');
7
7
  const getters = require('./getters.cjs');
8
+ const queryKeyDefs = require('./query-key-defs.cjs');
9
+ const serializers = require('./serializers.cjs');
8
10
 
11
+ function createKanbanPrefetchForRoute(adapter) {
12
+ return async function prefetchForRoute(key, qc, params) {
13
+ switch (key) {
14
+ case "boards": {
15
+ const result = await getters.getAllBoards(adapter, { limit: 50, offset: 0 });
16
+ qc.setQueryData(
17
+ queryKeyDefs.KANBAN_QUERY_KEYS.boardsList({}),
18
+ result.items.map(serializers.serializeBoard)
19
+ );
20
+ break;
21
+ }
22
+ case "board": {
23
+ const boardId = params?.boardId ?? "";
24
+ if (boardId) {
25
+ const board = await getters.getBoardById(adapter, boardId);
26
+ qc.setQueryData(
27
+ queryKeyDefs.KANBAN_QUERY_KEYS.boardDetail(boardId),
28
+ board ? serializers.serializeBoard(board) : null
29
+ );
30
+ }
31
+ break;
32
+ }
33
+ }
34
+ };
35
+ }
9
36
  const kanbanBackendPlugin = (hooks) => api.defineBackendPlugin({
10
37
  name: "kanban",
11
38
  dbPlugin: db.kanbanSchema,
12
39
  api: (adapter) => ({
13
40
  getAllBoards: (params) => getters.getAllBoards(adapter, params),
14
- getBoardById: (id) => getters.getBoardById(adapter, id)
41
+ getBoardById: (id) => getters.getBoardById(adapter, id),
42
+ prefetchForRoute: createKanbanPrefetchForRoute(adapter)
15
43
  }),
16
44
  routes: (adapter) => {
17
45
  const listBoards = api.createEndpoint(
@@ -3,13 +3,41 @@ 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 { KANBAN_QUERY_KEYS } from './query-key-defs.mjs';
7
+ import { serializeBoard } from './serializers.mjs';
6
8
 
9
+ function createKanbanPrefetchForRoute(adapter) {
10
+ return async function prefetchForRoute(key, qc, params) {
11
+ switch (key) {
12
+ case "boards": {
13
+ const result = await getAllBoards(adapter, { limit: 50, offset: 0 });
14
+ qc.setQueryData(
15
+ KANBAN_QUERY_KEYS.boardsList({}),
16
+ result.items.map(serializeBoard)
17
+ );
18
+ break;
19
+ }
20
+ case "board": {
21
+ const boardId = params?.boardId ?? "";
22
+ if (boardId) {
23
+ const board = await getBoardById(adapter, boardId);
24
+ qc.setQueryData(
25
+ KANBAN_QUERY_KEYS.boardDetail(boardId),
26
+ board ? serializeBoard(board) : null
27
+ );
28
+ }
29
+ break;
30
+ }
31
+ }
32
+ };
33
+ }
7
34
  const kanbanBackendPlugin = (hooks) => defineBackendPlugin({
8
35
  name: "kanban",
9
36
  dbPlugin: kanbanSchema,
10
37
  api: (adapter) => ({
11
38
  getAllBoards: (params) => getAllBoards(adapter, params),
12
- getBoardById: (id) => getBoardById(adapter, id)
39
+ getBoardById: (id) => getBoardById(adapter, id),
40
+ prefetchForRoute: createKanbanPrefetchForRoute(adapter)
13
41
  }),
14
42
  routes: (adapter) => {
15
43
  const listBoards = createEndpoint(
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ function boardsListDiscriminator(params) {
4
+ return {
5
+ slug: params?.slug,
6
+ ownerId: params?.ownerId,
7
+ organizationId: params?.organizationId,
8
+ limit: params?.limit ?? 50,
9
+ offset: params?.offset ?? 0
10
+ };
11
+ }
12
+ const KANBAN_QUERY_KEYS = {
13
+ /**
14
+ * Key for boards.list(params) query.
15
+ * Full key: ["boards", "list", { slug, ownerId, organizationId, limit, offset }]
16
+ */
17
+ boardsList: (params) => ["boards", "list", boardsListDiscriminator(params)],
18
+ /**
19
+ * Key for boards.detail(boardId) query.
20
+ * Full key: ["boards", "detail", boardId]
21
+ */
22
+ boardDetail: (boardId) => ["boards", "detail", boardId]
23
+ };
24
+
25
+ exports.KANBAN_QUERY_KEYS = KANBAN_QUERY_KEYS;
26
+ exports.boardsListDiscriminator = boardsListDiscriminator;
@@ -0,0 +1,23 @@
1
+ function boardsListDiscriminator(params) {
2
+ return {
3
+ slug: params?.slug,
4
+ ownerId: params?.ownerId,
5
+ organizationId: params?.organizationId,
6
+ limit: params?.limit ?? 50,
7
+ offset: params?.offset ?? 0
8
+ };
9
+ }
10
+ const KANBAN_QUERY_KEYS = {
11
+ /**
12
+ * Key for boards.list(params) query.
13
+ * Full key: ["boards", "list", { slug, ownerId, organizationId, limit, offset }]
14
+ */
15
+ boardsList: (params) => ["boards", "list", boardsListDiscriminator(params)],
16
+ /**
17
+ * Key for boards.detail(boardId) query.
18
+ * Full key: ["boards", "detail", boardId]
19
+ */
20
+ boardDetail: (boardId) => ["boards", "detail", boardId]
21
+ };
22
+
23
+ export { KANBAN_QUERY_KEYS, boardsListDiscriminator };
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ function serializeTask(task) {
4
+ return {
5
+ ...task,
6
+ completedAt: task.completedAt?.toISOString(),
7
+ createdAt: task.createdAt.toISOString(),
8
+ updatedAt: task.updatedAt.toISOString()
9
+ };
10
+ }
11
+ function serializeColumn(col) {
12
+ return {
13
+ ...col,
14
+ createdAt: col.createdAt.toISOString(),
15
+ updatedAt: col.updatedAt.toISOString(),
16
+ tasks: col.tasks.map(serializeTask)
17
+ };
18
+ }
19
+ function serializeBoard(board) {
20
+ return {
21
+ ...board,
22
+ createdAt: board.createdAt.toISOString(),
23
+ updatedAt: board.updatedAt.toISOString(),
24
+ columns: board.columns.map(serializeColumn)
25
+ };
26
+ }
27
+
28
+ exports.serializeBoard = serializeBoard;
29
+ exports.serializeColumn = serializeColumn;
30
+ exports.serializeTask = serializeTask;
@@ -0,0 +1,26 @@
1
+ function serializeTask(task) {
2
+ return {
3
+ ...task,
4
+ completedAt: task.completedAt?.toISOString(),
5
+ createdAt: task.createdAt.toISOString(),
6
+ updatedAt: task.updatedAt.toISOString()
7
+ };
8
+ }
9
+ function serializeColumn(col) {
10
+ return {
11
+ ...col,
12
+ createdAt: col.createdAt.toISOString(),
13
+ updatedAt: col.updatedAt.toISOString(),
14
+ tasks: col.tasks.map(serializeTask)
15
+ };
16
+ }
17
+ function serializeBoard(board) {
18
+ return {
19
+ ...board,
20
+ createdAt: board.createdAt.toISOString(),
21
+ updatedAt: board.updatedAt.toISOString(),
22
+ columns: board.columns.map(serializeColumn)
23
+ };
24
+ }
25
+
26
+ export { serializeBoard, serializeColumn, serializeTask };
@@ -51,6 +51,11 @@ function createBoardsLoader(config) {
51
51
  await hooks.onLoadError(error, context);
52
52
  }
53
53
  } catch (error) {
54
+ if (client.isConnectionError(error)) {
55
+ console.warn(
56
+ "[btst/kanban] route.loader() failed \u2014 no server running at build time. Use myStack.api.kanban.prefetchForRoute() for SSG data prefetching."
57
+ );
58
+ }
54
59
  if (hooks?.onLoadError) {
55
60
  await hooks.onLoadError(error, context);
56
61
  }
@@ -103,6 +108,11 @@ function createBoardLoader(boardId, config) {
103
108
  await hooks.onLoadError(error, context);
104
109
  }
105
110
  } catch (error) {
111
+ if (client.isConnectionError(error)) {
112
+ console.warn(
113
+ "[btst/kanban] route.loader() failed \u2014 no server running at build time. Use myStack.api.kanban.prefetchForRoute() for SSG data prefetching."
114
+ );
115
+ }
106
116
  if (hooks?.onLoadError) {
107
117
  await hooks.onLoadError(error, context);
108
118
  }
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { defineClientPlugin, createApiClient } from '@btst/stack/plugins/client';
2
+ import { defineClientPlugin, createApiClient, 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';
@@ -49,6 +49,11 @@ function createBoardsLoader(config) {
49
49
  await hooks.onLoadError(error, context);
50
50
  }
51
51
  } catch (error) {
52
+ if (isConnectionError(error)) {
53
+ console.warn(
54
+ "[btst/kanban] route.loader() failed \u2014 no server running at build time. Use myStack.api.kanban.prefetchForRoute() for SSG data prefetching."
55
+ );
56
+ }
52
57
  if (hooks?.onLoadError) {
53
58
  await hooks.onLoadError(error, context);
54
59
  }
@@ -101,6 +106,11 @@ function createBoardLoader(boardId, config) {
101
106
  await hooks.onLoadError(error, context);
102
107
  }
103
108
  } catch (error) {
109
+ if (isConnectionError(error)) {
110
+ console.warn(
111
+ "[btst/kanban] route.loader() failed \u2014 no server running at build time. Use myStack.api.kanban.prefetchForRoute() for SSG data prefetching."
112
+ );
113
+ }
104
114
  if (hooks?.onLoadError) {
105
115
  await hooks.onLoadError(error, context);
106
116
  }
@@ -2,6 +2,11 @@
2
2
 
3
3
  const client = require('better-call/client');
4
4
 
5
+ function isConnectionError(err) {
6
+ if (!(err instanceof Error)) return false;
7
+ const code = err.cause?.code ?? err.code;
8
+ return err.message.includes("ECONNREFUSED") || err.message.includes("fetch failed") || err.message.includes("ERR_CONNECTION_REFUSED") || code === "ECONNREFUSED" || code === "ERR_CONNECTION_REFUSED";
9
+ }
5
10
  function createApiClient(options) {
6
11
  const { baseURL = "", basePath = "/" } = options ?? {};
7
12
  const normalizedBaseURL = baseURL ? baseURL.replace(/\/$/, "") : "";
@@ -14,3 +19,4 @@ function createApiClient(options) {
14
19
  }
15
20
 
16
21
  exports.createApiClient = createApiClient;
22
+ exports.isConnectionError = isConnectionError;
@@ -1,5 +1,10 @@
1
1
  import { createClient } from 'better-call/client';
2
2
 
3
+ function isConnectionError(err) {
4
+ if (!(err instanceof Error)) return false;
5
+ const code = err.cause?.code ?? err.code;
6
+ return err.message.includes("ECONNREFUSED") || err.message.includes("fetch failed") || err.message.includes("ERR_CONNECTION_REFUSED") || code === "ECONNREFUSED" || code === "ERR_CONNECTION_REFUSED";
7
+ }
3
8
  function createApiClient(options) {
4
9
  const { baseURL = "", basePath = "/" } = options ?? {};
5
10
  const normalizedBaseURL = baseURL ? baseURL.replace(/\/$/, "") : "";
@@ -11,4 +16,4 @@ function createApiClient(options) {
11
16
  });
12
17
  }
13
18
 
14
- export { createApiClient };
19
+ export { createApiClient, isConnectionError };
@@ -2,6 +2,8 @@
2
2
 
3
3
  const plugin = require('../../../packages/stack/src/plugins/blog/api/plugin.cjs');
4
4
  const getters = require('../../../packages/stack/src/plugins/blog/api/getters.cjs');
5
+ const serializers = require('../../../packages/stack/src/plugins/blog/api/serializers.cjs');
6
+ const queryKeyDefs = require('../../../packages/stack/src/plugins/blog/api/query-key-defs.cjs');
5
7
  const plugins_blog_queryKeys = require('../query-keys.cjs');
6
8
 
7
9
 
@@ -12,4 +14,7 @@ exports.blogBackendPlugin = plugin.blogBackendPlugin;
12
14
  exports.getAllPosts = getters.getAllPosts;
13
15
  exports.getAllTags = getters.getAllTags;
14
16
  exports.getPostBySlug = getters.getPostBySlug;
17
+ exports.serializePost = serializers.serializePost;
18
+ exports.serializeTag = serializers.serializeTag;
19
+ exports.BLOG_QUERY_KEYS = queryKeyDefs.BLOG_QUERY_KEYS;
15
20
  exports.createBlogQueryKeys = plugins_blog_queryKeys.createBlogQueryKeys;