@btst/stack 2.9.2 → 2.9.4
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.
- package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +22 -11
- package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +22 -11
- package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +71 -39
- package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +71 -39
- package/dist/packages/stack/src/plugins/comments/client/plugin.cjs +62 -2
- package/dist/packages/stack/src/plugins/comments/client/plugin.mjs +63 -3
- package/dist/packages/stack/src/plugins/comments/client/utils.cjs +2 -11
- package/dist/packages/stack/src/plugins/comments/client/utils.mjs +2 -11
- package/dist/packages/stack/src/plugins/comments/error-utils.cjs +15 -0
- package/dist/packages/stack/src/plugins/comments/error-utils.mjs +13 -0
- package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +59 -31
- package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +59 -31
- package/dist/packages/stack/src/plugins/media/db.cjs +10 -2
- package/dist/packages/stack/src/plugins/media/db.mjs +10 -2
- package/dist/packages/stack/src/plugins/ui-builder/client/plugin.cjs +52 -25
- package/dist/packages/stack/src/plugins/ui-builder/client/plugin.mjs +53 -26
- package/dist/packages/stack/src/plugins/utils.cjs +6 -0
- package/dist/packages/stack/src/plugins/utils.mjs +5 -1
- package/dist/plugins/client/index.cjs +2 -0
- package/dist/plugins/client/index.d.cts +15 -1
- package/dist/plugins/client/index.d.mts +15 -1
- package/dist/plugins/client/index.d.ts +15 -1
- package/dist/plugins/client/index.mjs +1 -1
- package/dist/plugins/comments/client/index.d.cts +5 -0
- package/dist/plugins/comments/client/index.d.mts +5 -0
- package/dist/plugins/comments/client/index.d.ts +5 -0
- package/dist/plugins/comments/query-keys.cjs +4 -4
- package/dist/plugins/comments/query-keys.mjs +1 -1
- package/package.json +1 -1
- package/src/__tests__/client-plugin-ssr-loaders.test.ts +329 -0
- package/src/plugins/blog/client/plugin.tsx +23 -14
- package/src/plugins/client/index.ts +2 -0
- package/src/plugins/cms/client/plugin.tsx +73 -42
- package/src/plugins/comments/client/plugin.tsx +82 -2
- package/src/plugins/comments/client/utils.ts +2 -14
- package/src/plugins/comments/error-utils.ts +17 -0
- package/src/plugins/comments/query-keys.ts +1 -1
- package/src/plugins/form-builder/client/plugin.tsx +59 -35
- package/src/plugins/media/__tests__/plugin.test.ts +4 -4
- package/src/plugins/media/db.ts +8 -0
- package/src/plugins/ui-builder/client/plugin.tsx +57 -27
- package/src/plugins/utils.ts +18 -0
|
@@ -5,6 +5,7 @@ const React = require('react');
|
|
|
5
5
|
const client = require('@btst/stack/plugins/client');
|
|
6
6
|
const yar = require('@btst/yar');
|
|
7
7
|
const plugins_cms_queryKeys = require('../../../../../../plugins/cms/query-keys.cjs');
|
|
8
|
+
const utils = require('../../utils.cjs');
|
|
8
9
|
const schemas = require('../schemas.cjs');
|
|
9
10
|
|
|
10
11
|
const PageListPageComponent = React.lazy(
|
|
@@ -29,6 +30,18 @@ function createPageListLoader(config) {
|
|
|
29
30
|
apiBasePath,
|
|
30
31
|
headers
|
|
31
32
|
};
|
|
33
|
+
const client$1 = client.createApiClient({
|
|
34
|
+
baseURL: apiBaseURL,
|
|
35
|
+
basePath: apiBasePath
|
|
36
|
+
});
|
|
37
|
+
const queries = plugins_cms_queryKeys.createCMSQueryKeys(client$1, headers);
|
|
38
|
+
const limit = 20;
|
|
39
|
+
const listQuery = queries.cmsContent.list({
|
|
40
|
+
typeSlug,
|
|
41
|
+
limit,
|
|
42
|
+
offset: 0
|
|
43
|
+
});
|
|
44
|
+
const uiBuilderListQueryKey = [...listQuery.queryKey, "ui-builder"];
|
|
32
45
|
try {
|
|
33
46
|
if (hooks?.beforeLoadPageList) {
|
|
34
47
|
await client.runClientHookWithShim(
|
|
@@ -36,19 +49,8 @@ function createPageListLoader(config) {
|
|
|
36
49
|
"Load prevented by beforeLoadPageList hook"
|
|
37
50
|
);
|
|
38
51
|
}
|
|
39
|
-
const client$1 = client.createApiClient({
|
|
40
|
-
baseURL: apiBaseURL,
|
|
41
|
-
basePath: apiBasePath
|
|
42
|
-
});
|
|
43
|
-
const queries = plugins_cms_queryKeys.createCMSQueryKeys(client$1, headers);
|
|
44
|
-
const limit = 20;
|
|
45
|
-
const listQuery = queries.cmsContent.list({
|
|
46
|
-
typeSlug,
|
|
47
|
-
limit,
|
|
48
|
-
offset: 0
|
|
49
|
-
});
|
|
50
52
|
await queryClient.prefetchInfiniteQuery({
|
|
51
|
-
queryKey:
|
|
53
|
+
queryKey: uiBuilderListQueryKey,
|
|
52
54
|
queryFn: async ({ pageParam = 0 }) => {
|
|
53
55
|
const response = await client$1("/content/:typeSlug", {
|
|
54
56
|
method: "GET",
|
|
@@ -67,14 +69,28 @@ function createPageListLoader(config) {
|
|
|
67
69
|
await hooks.afterLoadPageList(context);
|
|
68
70
|
}
|
|
69
71
|
const queryState = queryClient.getQueryState([
|
|
70
|
-
...
|
|
71
|
-
"ui-builder"
|
|
72
|
+
...uiBuilderListQueryKey
|
|
72
73
|
]);
|
|
73
74
|
if (queryState?.error && hooks?.onLoadError) {
|
|
74
75
|
const error = queryState.error instanceof Error ? queryState.error : new Error(String(queryState.error));
|
|
75
76
|
await hooks.onLoadError(error, context);
|
|
76
77
|
}
|
|
77
78
|
} catch (error) {
|
|
79
|
+
if (client.isConnectionError(error)) {
|
|
80
|
+
console.warn(
|
|
81
|
+
"[btst/ui-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.uiBuilder.prefetchForRoute() for SSG data prefetching."
|
|
82
|
+
);
|
|
83
|
+
} else {
|
|
84
|
+
const errToStore = utils.createSanitizedSSRLoaderError();
|
|
85
|
+
await queryClient.prefetchInfiniteQuery({
|
|
86
|
+
queryKey: uiBuilderListQueryKey,
|
|
87
|
+
queryFn: () => {
|
|
88
|
+
throw errToStore;
|
|
89
|
+
},
|
|
90
|
+
initialPageParam: 0,
|
|
91
|
+
retry: false
|
|
92
|
+
});
|
|
93
|
+
}
|
|
78
94
|
if (hooks?.onLoadError) {
|
|
79
95
|
await hooks.onLoadError(error, context);
|
|
80
96
|
}
|
|
@@ -95,6 +111,12 @@ function createPageBuilderLoader(id, config) {
|
|
|
95
111
|
apiBasePath,
|
|
96
112
|
headers
|
|
97
113
|
};
|
|
114
|
+
const client$1 = client.createApiClient({
|
|
115
|
+
baseURL: apiBaseURL,
|
|
116
|
+
basePath: apiBasePath
|
|
117
|
+
});
|
|
118
|
+
const queries = plugins_cms_queryKeys.createCMSQueryKeys(client$1, headers);
|
|
119
|
+
const pageQuery = id ? queries.cmsContent.detail(typeSlug, id) : void 0;
|
|
98
120
|
try {
|
|
99
121
|
if (hooks?.beforeLoadPageBuilder) {
|
|
100
122
|
await client.runClientHookWithShim(
|
|
@@ -102,29 +124,34 @@ function createPageBuilderLoader(id, config) {
|
|
|
102
124
|
"Load prevented by beforeLoadPageBuilder hook"
|
|
103
125
|
);
|
|
104
126
|
}
|
|
105
|
-
const client$1 = client.createApiClient({
|
|
106
|
-
baseURL: apiBaseURL,
|
|
107
|
-
basePath: apiBasePath
|
|
108
|
-
});
|
|
109
|
-
const queries = plugins_cms_queryKeys.createCMSQueryKeys(client$1, headers);
|
|
110
127
|
if (id) {
|
|
111
|
-
await queryClient.prefetchQuery(
|
|
112
|
-
queries.cmsContent.detail(typeSlug, id)
|
|
113
|
-
);
|
|
128
|
+
await queryClient.prefetchQuery(pageQuery);
|
|
114
129
|
}
|
|
115
130
|
if (hooks?.afterLoadPageBuilder) {
|
|
116
131
|
await hooks.afterLoadPageBuilder(id, context);
|
|
117
132
|
}
|
|
118
133
|
if (id) {
|
|
119
|
-
const queryState = queryClient.getQueryState(
|
|
120
|
-
queries.cmsContent.detail(typeSlug, id).queryKey
|
|
121
|
-
);
|
|
134
|
+
const queryState = queryClient.getQueryState(pageQuery.queryKey);
|
|
122
135
|
if (queryState?.error && hooks?.onLoadError) {
|
|
123
136
|
const error = queryState.error instanceof Error ? queryState.error : new Error(String(queryState.error));
|
|
124
137
|
await hooks.onLoadError(error, context);
|
|
125
138
|
}
|
|
126
139
|
}
|
|
127
140
|
} catch (error) {
|
|
141
|
+
if (client.isConnectionError(error)) {
|
|
142
|
+
console.warn(
|
|
143
|
+
"[btst/ui-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.uiBuilder.prefetchForRoute() for SSG data prefetching."
|
|
144
|
+
);
|
|
145
|
+
} else if (pageQuery) {
|
|
146
|
+
const errToStore = utils.createSanitizedSSRLoaderError();
|
|
147
|
+
await queryClient.prefetchQuery({
|
|
148
|
+
queryKey: pageQuery.queryKey,
|
|
149
|
+
queryFn: () => {
|
|
150
|
+
throw errToStore;
|
|
151
|
+
},
|
|
152
|
+
retry: false
|
|
153
|
+
});
|
|
154
|
+
}
|
|
128
155
|
if (hooks?.onLoadError) {
|
|
129
156
|
await hooks.onLoadError(error, context);
|
|
130
157
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { lazy } from 'react';
|
|
3
|
-
import { defineClientPlugin, createApiClient, runClientHookWithShim } 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 { createCMSQueryKeys } from '../../../../../../plugins/cms/query-keys.mjs';
|
|
6
|
+
import { createSanitizedSSRLoaderError } from '../../utils.mjs';
|
|
6
7
|
import { UI_BUILDER_TYPE_SLUG } from '../schemas.mjs';
|
|
7
8
|
|
|
8
9
|
const PageListPageComponent = lazy(
|
|
@@ -27,6 +28,18 @@ function createPageListLoader(config) {
|
|
|
27
28
|
apiBasePath,
|
|
28
29
|
headers
|
|
29
30
|
};
|
|
31
|
+
const client = createApiClient({
|
|
32
|
+
baseURL: apiBaseURL,
|
|
33
|
+
basePath: apiBasePath
|
|
34
|
+
});
|
|
35
|
+
const queries = createCMSQueryKeys(client, headers);
|
|
36
|
+
const limit = 20;
|
|
37
|
+
const listQuery = queries.cmsContent.list({
|
|
38
|
+
typeSlug,
|
|
39
|
+
limit,
|
|
40
|
+
offset: 0
|
|
41
|
+
});
|
|
42
|
+
const uiBuilderListQueryKey = [...listQuery.queryKey, "ui-builder"];
|
|
30
43
|
try {
|
|
31
44
|
if (hooks?.beforeLoadPageList) {
|
|
32
45
|
await runClientHookWithShim(
|
|
@@ -34,19 +47,8 @@ function createPageListLoader(config) {
|
|
|
34
47
|
"Load prevented by beforeLoadPageList hook"
|
|
35
48
|
);
|
|
36
49
|
}
|
|
37
|
-
const client = createApiClient({
|
|
38
|
-
baseURL: apiBaseURL,
|
|
39
|
-
basePath: apiBasePath
|
|
40
|
-
});
|
|
41
|
-
const queries = createCMSQueryKeys(client, headers);
|
|
42
|
-
const limit = 20;
|
|
43
|
-
const listQuery = queries.cmsContent.list({
|
|
44
|
-
typeSlug,
|
|
45
|
-
limit,
|
|
46
|
-
offset: 0
|
|
47
|
-
});
|
|
48
50
|
await queryClient.prefetchInfiniteQuery({
|
|
49
|
-
queryKey:
|
|
51
|
+
queryKey: uiBuilderListQueryKey,
|
|
50
52
|
queryFn: async ({ pageParam = 0 }) => {
|
|
51
53
|
const response = await client("/content/:typeSlug", {
|
|
52
54
|
method: "GET",
|
|
@@ -65,14 +67,28 @@ function createPageListLoader(config) {
|
|
|
65
67
|
await hooks.afterLoadPageList(context);
|
|
66
68
|
}
|
|
67
69
|
const queryState = queryClient.getQueryState([
|
|
68
|
-
...
|
|
69
|
-
"ui-builder"
|
|
70
|
+
...uiBuilderListQueryKey
|
|
70
71
|
]);
|
|
71
72
|
if (queryState?.error && hooks?.onLoadError) {
|
|
72
73
|
const error = queryState.error instanceof Error ? queryState.error : new Error(String(queryState.error));
|
|
73
74
|
await hooks.onLoadError(error, context);
|
|
74
75
|
}
|
|
75
76
|
} catch (error) {
|
|
77
|
+
if (isConnectionError(error)) {
|
|
78
|
+
console.warn(
|
|
79
|
+
"[btst/ui-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.uiBuilder.prefetchForRoute() for SSG data prefetching."
|
|
80
|
+
);
|
|
81
|
+
} else {
|
|
82
|
+
const errToStore = createSanitizedSSRLoaderError();
|
|
83
|
+
await queryClient.prefetchInfiniteQuery({
|
|
84
|
+
queryKey: uiBuilderListQueryKey,
|
|
85
|
+
queryFn: () => {
|
|
86
|
+
throw errToStore;
|
|
87
|
+
},
|
|
88
|
+
initialPageParam: 0,
|
|
89
|
+
retry: false
|
|
90
|
+
});
|
|
91
|
+
}
|
|
76
92
|
if (hooks?.onLoadError) {
|
|
77
93
|
await hooks.onLoadError(error, context);
|
|
78
94
|
}
|
|
@@ -93,6 +109,12 @@ function createPageBuilderLoader(id, config) {
|
|
|
93
109
|
apiBasePath,
|
|
94
110
|
headers
|
|
95
111
|
};
|
|
112
|
+
const client = createApiClient({
|
|
113
|
+
baseURL: apiBaseURL,
|
|
114
|
+
basePath: apiBasePath
|
|
115
|
+
});
|
|
116
|
+
const queries = createCMSQueryKeys(client, headers);
|
|
117
|
+
const pageQuery = id ? queries.cmsContent.detail(typeSlug, id) : void 0;
|
|
96
118
|
try {
|
|
97
119
|
if (hooks?.beforeLoadPageBuilder) {
|
|
98
120
|
await runClientHookWithShim(
|
|
@@ -100,29 +122,34 @@ function createPageBuilderLoader(id, config) {
|
|
|
100
122
|
"Load prevented by beforeLoadPageBuilder hook"
|
|
101
123
|
);
|
|
102
124
|
}
|
|
103
|
-
const client = createApiClient({
|
|
104
|
-
baseURL: apiBaseURL,
|
|
105
|
-
basePath: apiBasePath
|
|
106
|
-
});
|
|
107
|
-
const queries = createCMSQueryKeys(client, headers);
|
|
108
125
|
if (id) {
|
|
109
|
-
await queryClient.prefetchQuery(
|
|
110
|
-
queries.cmsContent.detail(typeSlug, id)
|
|
111
|
-
);
|
|
126
|
+
await queryClient.prefetchQuery(pageQuery);
|
|
112
127
|
}
|
|
113
128
|
if (hooks?.afterLoadPageBuilder) {
|
|
114
129
|
await hooks.afterLoadPageBuilder(id, context);
|
|
115
130
|
}
|
|
116
131
|
if (id) {
|
|
117
|
-
const queryState = queryClient.getQueryState(
|
|
118
|
-
queries.cmsContent.detail(typeSlug, id).queryKey
|
|
119
|
-
);
|
|
132
|
+
const queryState = queryClient.getQueryState(pageQuery.queryKey);
|
|
120
133
|
if (queryState?.error && hooks?.onLoadError) {
|
|
121
134
|
const error = queryState.error instanceof Error ? queryState.error : new Error(String(queryState.error));
|
|
122
135
|
await hooks.onLoadError(error, context);
|
|
123
136
|
}
|
|
124
137
|
}
|
|
125
138
|
} catch (error) {
|
|
139
|
+
if (isConnectionError(error)) {
|
|
140
|
+
console.warn(
|
|
141
|
+
"[btst/ui-builder] route.loader() failed \u2014 no server running at build time. Use myStack.api.uiBuilder.prefetchForRoute() for SSG data prefetching."
|
|
142
|
+
);
|
|
143
|
+
} else if (pageQuery) {
|
|
144
|
+
const errToStore = createSanitizedSSRLoaderError();
|
|
145
|
+
await queryClient.prefetchQuery({
|
|
146
|
+
queryKey: pageQuery.queryKey,
|
|
147
|
+
queryFn: () => {
|
|
148
|
+
throw errToStore;
|
|
149
|
+
},
|
|
150
|
+
retry: false
|
|
151
|
+
});
|
|
152
|
+
}
|
|
126
153
|
if (hooks?.onLoadError) {
|
|
127
154
|
await hooks.onLoadError(error, context);
|
|
128
155
|
}
|
|
@@ -47,6 +47,10 @@ function isConnectionError(err) {
|
|
|
47
47
|
const code = err.cause?.code ?? err.code;
|
|
48
48
|
return err.message.includes("ECONNREFUSED") || err.message.includes("fetch failed") || err.message.includes("ERR_CONNECTION_REFUSED") || code === "ECONNREFUSED" || code === "ERR_CONNECTION_REFUSED";
|
|
49
49
|
}
|
|
50
|
+
const SSR_LOADER_ERROR_MESSAGE = "Failed to load data.";
|
|
51
|
+
function createSanitizedSSRLoaderError() {
|
|
52
|
+
return new Error(SSR_LOADER_ERROR_MESSAGE);
|
|
53
|
+
}
|
|
50
54
|
function createApiClient(options) {
|
|
51
55
|
const { baseURL = "", basePath = "/" } = options ?? {};
|
|
52
56
|
const normalizedBaseURL = baseURL ? baseURL.replace(/\/$/, "") : "";
|
|
@@ -58,7 +62,9 @@ function createApiClient(options) {
|
|
|
58
62
|
});
|
|
59
63
|
}
|
|
60
64
|
|
|
65
|
+
exports.SSR_LOADER_ERROR_MESSAGE = SSR_LOADER_ERROR_MESSAGE;
|
|
61
66
|
exports.createApiClient = createApiClient;
|
|
67
|
+
exports.createSanitizedSSRLoaderError = createSanitizedSSRLoaderError;
|
|
62
68
|
exports.isConnectionError = isConnectionError;
|
|
63
69
|
exports.runClientHookWithShim = runClientHookWithShim;
|
|
64
70
|
exports.runHookWithShim = runHookWithShim;
|
|
@@ -45,6 +45,10 @@ function isConnectionError(err) {
|
|
|
45
45
|
const code = err.cause?.code ?? err.code;
|
|
46
46
|
return err.message.includes("ECONNREFUSED") || err.message.includes("fetch failed") || err.message.includes("ERR_CONNECTION_REFUSED") || code === "ECONNREFUSED" || code === "ERR_CONNECTION_REFUSED";
|
|
47
47
|
}
|
|
48
|
+
const SSR_LOADER_ERROR_MESSAGE = "Failed to load data.";
|
|
49
|
+
function createSanitizedSSRLoaderError() {
|
|
50
|
+
return new Error(SSR_LOADER_ERROR_MESSAGE);
|
|
51
|
+
}
|
|
48
52
|
function createApiClient(options) {
|
|
49
53
|
const { baseURL = "", basePath = "/" } = options ?? {};
|
|
50
54
|
const normalizedBaseURL = baseURL ? baseURL.replace(/\/$/, "") : "";
|
|
@@ -56,4 +60,4 @@ function createApiClient(options) {
|
|
|
56
60
|
});
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
export { createApiClient, isConnectionError, runClientHookWithShim, runHookWithShim };
|
|
63
|
+
export { SSR_LOADER_ERROR_MESSAGE, createApiClient, createSanitizedSSRLoaderError, isConnectionError, runClientHookWithShim, runHookWithShim };
|
|
@@ -8,7 +8,9 @@ function defineClientPlugin(plugin) {
|
|
|
8
8
|
return plugin;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
exports.SSR_LOADER_ERROR_MESSAGE = utils.SSR_LOADER_ERROR_MESSAGE;
|
|
11
12
|
exports.createApiClient = utils.createApiClient;
|
|
13
|
+
exports.createSanitizedSSRLoaderError = utils.createSanitizedSSRLoaderError;
|
|
12
14
|
exports.isConnectionError = utils.isConnectionError;
|
|
13
15
|
exports.runClientHookWithShim = utils.runClientHookWithShim;
|
|
14
16
|
exports.createRoute = yar.createRoute;
|
|
@@ -20,6 +20,20 @@ declare function runClientHookWithShim<T>(hookFn: () => Promise<T> | T, defaultM
|
|
|
20
20
|
* `route.loader()` is called during `next build` with no HTTP server running.
|
|
21
21
|
*/
|
|
22
22
|
declare function isConnectionError(err: unknown): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Public-safe message used when SSR loader failures are intentionally seeded
|
|
25
|
+
* into React Query so Error Boundaries can render on the client.
|
|
26
|
+
*
|
|
27
|
+
* Never include raw server error text here because dehydrated query state can
|
|
28
|
+
* be serialized into HTML.
|
|
29
|
+
*/
|
|
30
|
+
declare const SSR_LOADER_ERROR_MESSAGE = "Failed to load data.";
|
|
31
|
+
/**
|
|
32
|
+
* Creates a sanitized Error for SSR loader cache seeding.
|
|
33
|
+
*
|
|
34
|
+
* Use this instead of storing raw server errors in dehydrated query state.
|
|
35
|
+
*/
|
|
36
|
+
declare function createSanitizedSSRLoaderError(): Error;
|
|
23
37
|
|
|
24
38
|
interface CreateApiClientOptions {
|
|
25
39
|
baseURL?: string;
|
|
@@ -67,4 +81,4 @@ declare function createApiClient<TRouter extends Router | Record<string, Endpoin
|
|
|
67
81
|
*/
|
|
68
82
|
declare function defineClientPlugin<TOverrides = Record<string, never>, TRoutes extends Record<string, Route> = Record<string, Route>>(plugin: ClientPlugin<TOverrides, TRoutes>): ClientPlugin<TOverrides, TRoutes>;
|
|
69
83
|
|
|
70
|
-
export { ClientPlugin, createApiClient, defineClientPlugin, isConnectionError, runClientHookWithShim };
|
|
84
|
+
export { ClientPlugin, SSR_LOADER_ERROR_MESSAGE, createApiClient, createSanitizedSSRLoaderError, defineClientPlugin, isConnectionError, runClientHookWithShim };
|
|
@@ -20,6 +20,20 @@ declare function runClientHookWithShim<T>(hookFn: () => Promise<T> | T, defaultM
|
|
|
20
20
|
* `route.loader()` is called during `next build` with no HTTP server running.
|
|
21
21
|
*/
|
|
22
22
|
declare function isConnectionError(err: unknown): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Public-safe message used when SSR loader failures are intentionally seeded
|
|
25
|
+
* into React Query so Error Boundaries can render on the client.
|
|
26
|
+
*
|
|
27
|
+
* Never include raw server error text here because dehydrated query state can
|
|
28
|
+
* be serialized into HTML.
|
|
29
|
+
*/
|
|
30
|
+
declare const SSR_LOADER_ERROR_MESSAGE = "Failed to load data.";
|
|
31
|
+
/**
|
|
32
|
+
* Creates a sanitized Error for SSR loader cache seeding.
|
|
33
|
+
*
|
|
34
|
+
* Use this instead of storing raw server errors in dehydrated query state.
|
|
35
|
+
*/
|
|
36
|
+
declare function createSanitizedSSRLoaderError(): Error;
|
|
23
37
|
|
|
24
38
|
interface CreateApiClientOptions {
|
|
25
39
|
baseURL?: string;
|
|
@@ -67,4 +81,4 @@ declare function createApiClient<TRouter extends Router | Record<string, Endpoin
|
|
|
67
81
|
*/
|
|
68
82
|
declare function defineClientPlugin<TOverrides = Record<string, never>, TRoutes extends Record<string, Route> = Record<string, Route>>(plugin: ClientPlugin<TOverrides, TRoutes>): ClientPlugin<TOverrides, TRoutes>;
|
|
69
83
|
|
|
70
|
-
export { ClientPlugin, createApiClient, defineClientPlugin, isConnectionError, runClientHookWithShim };
|
|
84
|
+
export { ClientPlugin, SSR_LOADER_ERROR_MESSAGE, createApiClient, createSanitizedSSRLoaderError, defineClientPlugin, isConnectionError, runClientHookWithShim };
|
|
@@ -20,6 +20,20 @@ declare function runClientHookWithShim<T>(hookFn: () => Promise<T> | T, defaultM
|
|
|
20
20
|
* `route.loader()` is called during `next build` with no HTTP server running.
|
|
21
21
|
*/
|
|
22
22
|
declare function isConnectionError(err: unknown): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Public-safe message used when SSR loader failures are intentionally seeded
|
|
25
|
+
* into React Query so Error Boundaries can render on the client.
|
|
26
|
+
*
|
|
27
|
+
* Never include raw server error text here because dehydrated query state can
|
|
28
|
+
* be serialized into HTML.
|
|
29
|
+
*/
|
|
30
|
+
declare const SSR_LOADER_ERROR_MESSAGE = "Failed to load data.";
|
|
31
|
+
/**
|
|
32
|
+
* Creates a sanitized Error for SSR loader cache seeding.
|
|
33
|
+
*
|
|
34
|
+
* Use this instead of storing raw server errors in dehydrated query state.
|
|
35
|
+
*/
|
|
36
|
+
declare function createSanitizedSSRLoaderError(): Error;
|
|
23
37
|
|
|
24
38
|
interface CreateApiClientOptions {
|
|
25
39
|
baseURL?: string;
|
|
@@ -67,4 +81,4 @@ declare function createApiClient<TRouter extends Router | Record<string, Endpoin
|
|
|
67
81
|
*/
|
|
68
82
|
declare function defineClientPlugin<TOverrides = Record<string, never>, TRoutes extends Record<string, Route> = Record<string, Route>>(plugin: ClientPlugin<TOverrides, TRoutes>): ClientPlugin<TOverrides, TRoutes>;
|
|
69
83
|
|
|
70
|
-
export { ClientPlugin, createApiClient, defineClientPlugin, isConnectionError, runClientHookWithShim };
|
|
84
|
+
export { ClientPlugin, SSR_LOADER_ERROR_MESSAGE, createApiClient, createSanitizedSSRLoaderError, defineClientPlugin, isConnectionError, runClientHookWithShim };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { createApiClient, isConnectionError, runClientHookWithShim } from '../../packages/stack/src/plugins/utils.mjs';
|
|
1
|
+
export { SSR_LOADER_ERROR_MESSAGE, createApiClient, createSanitizedSSRLoaderError, isConnectionError, runClientHookWithShim } from '../../packages/stack/src/plugins/utils.mjs';
|
|
2
2
|
export { createRoute, createRouter } from '@btst/yar';
|
|
3
3
|
export { createClient } from 'better-call/client';
|
|
4
4
|
|
|
@@ -21,6 +21,11 @@ interface LoaderContext {
|
|
|
21
21
|
apiBasePath: string;
|
|
22
22
|
/** Optional headers for the request */
|
|
23
23
|
headers?: Headers;
|
|
24
|
+
/**
|
|
25
|
+
* Optional current user ID for SSR loaders that need user-scoped query keys.
|
|
26
|
+
* Hooks (e.g. beforeLoadUserComments) may populate this.
|
|
27
|
+
*/
|
|
28
|
+
currentUserId?: string;
|
|
24
29
|
/** Additional context properties */
|
|
25
30
|
[key: string]: unknown;
|
|
26
31
|
}
|
|
@@ -21,6 +21,11 @@ interface LoaderContext {
|
|
|
21
21
|
apiBasePath: string;
|
|
22
22
|
/** Optional headers for the request */
|
|
23
23
|
headers?: Headers;
|
|
24
|
+
/**
|
|
25
|
+
* Optional current user ID for SSR loaders that need user-scoped query keys.
|
|
26
|
+
* Hooks (e.g. beforeLoadUserComments) may populate this.
|
|
27
|
+
*/
|
|
28
|
+
currentUserId?: string;
|
|
24
29
|
/** Additional context properties */
|
|
25
30
|
[key: string]: unknown;
|
|
26
31
|
}
|
|
@@ -21,6 +21,11 @@ interface LoaderContext {
|
|
|
21
21
|
apiBasePath: string;
|
|
22
22
|
/** Optional headers for the request */
|
|
23
23
|
headers?: Headers;
|
|
24
|
+
/**
|
|
25
|
+
* Optional current user ID for SSR loaders that need user-scoped query keys.
|
|
26
|
+
* Hooks (e.g. beforeLoadUserComments) may populate this.
|
|
27
|
+
*/
|
|
28
|
+
currentUserId?: string;
|
|
24
29
|
/** Additional context properties */
|
|
25
30
|
[key: string]: unknown;
|
|
26
31
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const queryKeyFactory = require('@lukemorales/query-key-factory');
|
|
4
4
|
const queryKeyDefs = require('../../packages/stack/src/plugins/comments/api/query-key-defs.cjs');
|
|
5
|
-
const
|
|
5
|
+
const errorUtils = require('../../packages/stack/src/plugins/comments/error-utils.cjs');
|
|
6
6
|
|
|
7
7
|
function isErrorResponse(response) {
|
|
8
8
|
return typeof response === "object" && response !== null && "error" in response && response.error !== null && response.error !== void 0;
|
|
@@ -40,7 +40,7 @@ function createCommentsQueries(client, headers) {
|
|
|
40
40
|
headers
|
|
41
41
|
});
|
|
42
42
|
if (isErrorResponse(response)) {
|
|
43
|
-
throw
|
|
43
|
+
throw errorUtils.toError(response.error);
|
|
44
44
|
}
|
|
45
45
|
const data = response.data;
|
|
46
46
|
return data ?? { items: [], total: 0, limit: 20, offset: 0 };
|
|
@@ -63,7 +63,7 @@ function createCommentCountQueries(client, headers) {
|
|
|
63
63
|
headers
|
|
64
64
|
});
|
|
65
65
|
if (isErrorResponse(response)) {
|
|
66
|
-
throw
|
|
66
|
+
throw errorUtils.toError(response.error);
|
|
67
67
|
}
|
|
68
68
|
const data = response.data;
|
|
69
69
|
return data?.count ?? 0;
|
|
@@ -96,7 +96,7 @@ function createCommentsThreadQueries(client, headers) {
|
|
|
96
96
|
headers
|
|
97
97
|
});
|
|
98
98
|
if (isErrorResponse(response)) {
|
|
99
|
-
throw
|
|
99
|
+
throw errorUtils.toError(response.error);
|
|
100
100
|
}
|
|
101
101
|
const data = response.data;
|
|
102
102
|
return data ?? {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mergeQueryKeys, createQueryKeys } from '@lukemorales/query-key-factory';
|
|
2
2
|
import { commentsListDiscriminator, commentCountDiscriminator, commentsThreadDiscriminator } from '../../packages/stack/src/plugins/comments/api/query-key-defs.mjs';
|
|
3
|
-
import { toError } from '../../packages/stack/src/plugins/comments/
|
|
3
|
+
import { toError } from '../../packages/stack/src/plugins/comments/error-utils.mjs';
|
|
4
4
|
|
|
5
5
|
function isErrorResponse(response) {
|
|
6
6
|
return typeof response === "object" && response !== null && "error" in response && response.error !== null && response.error !== void 0;
|