@nestjs-ssr/react 0.2.0 → 0.2.2
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/README.md +1 -1
- package/dist/cli/init.js +339 -91
- package/dist/cli/init.mjs +341 -93
- package/dist/client.d.mts +319 -0
- package/dist/client.d.ts +319 -0
- package/dist/client.js +207 -0
- package/dist/client.mjs +200 -0
- package/dist/{index-C5Knql-9.d.mts → index-CaGD266H.d.ts} +2 -104
- package/dist/{index-C5Knql-9.d.ts → index-Dq1yt0sX.d.mts} +2 -104
- package/dist/index.d.mts +9 -321
- package/dist/index.d.ts +9 -321
- package/dist/index.js +144 -91
- package/dist/index.mjs +115 -63
- package/dist/render/index.d.mts +2 -1
- package/dist/render/index.d.ts +2 -1
- package/dist/render/index.js +134 -81
- package/dist/render/index.mjs +115 -63
- package/dist/render-response.interface-Dc-Kwb09.d.mts +104 -0
- package/dist/render-response.interface-Dc-Kwb09.d.ts +104 -0
- package/dist/templates/entry-client.tsx +6 -3
- package/dist/templates/entry-server.tsx +33 -2
- package/dist/templates/index.html +15 -12
- package/package.json +13 -1
- package/src/templates/entry-client.tsx +6 -3
- package/src/templates/entry-server.tsx +33 -2
- package/src/templates/index.html +15 -12
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { H as HeadData } from './render-response.interface-Dc-Kwb09.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Request context available to all React components.
|
|
7
|
+
* Contains safe request metadata that can be exposed to the client.
|
|
8
|
+
*
|
|
9
|
+
* Extend this interface to add app-specific properties (user, tenant, feature flags, etc.).
|
|
10
|
+
* Use module configuration to pass additional headers or cookies safely.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // Basic usage - use as-is
|
|
14
|
+
* const context: RenderContext = {
|
|
15
|
+
* url: '/users/123',
|
|
16
|
+
* path: '/users/123',
|
|
17
|
+
* query: { tab: 'profile' },
|
|
18
|
+
* params: { id: '123' },
|
|
19
|
+
* method: 'GET',
|
|
20
|
+
* };
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Extended usage - add custom properties for your app
|
|
24
|
+
* interface AppRenderContext extends RenderContext {
|
|
25
|
+
* user?: {
|
|
26
|
+
* id: string;
|
|
27
|
+
* name: string;
|
|
28
|
+
* email: string;
|
|
29
|
+
* roles: string[];
|
|
30
|
+
* };
|
|
31
|
+
* tenant?: {
|
|
32
|
+
* id: string;
|
|
33
|
+
* name: string;
|
|
34
|
+
* };
|
|
35
|
+
* featureFlags?: Record<string, boolean>;
|
|
36
|
+
* theme?: string; // From cookie
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* // Configure module to pass specific cookies/headers
|
|
40
|
+
* ReactSSRModule.forRoot({
|
|
41
|
+
* allowedCookies: ['theme', 'locale'],
|
|
42
|
+
* allowedHeaders: ['x-tenant-id'],
|
|
43
|
+
* })
|
|
44
|
+
*
|
|
45
|
+
* // Use in interceptor/controller
|
|
46
|
+
* const context: AppRenderContext = {
|
|
47
|
+
* ...baseContext,
|
|
48
|
+
* user: req.user,
|
|
49
|
+
* tenant: req.tenant,
|
|
50
|
+
* featureFlags: await featureFlagService.getFlags(req),
|
|
51
|
+
* };
|
|
52
|
+
*/
|
|
53
|
+
interface RenderContext {
|
|
54
|
+
url: string;
|
|
55
|
+
path: string;
|
|
56
|
+
query: Record<string, string | string[]>;
|
|
57
|
+
params: Record<string, string>;
|
|
58
|
+
method: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Generic type for React page component props.
|
|
63
|
+
* Spreads controller data directly as props (React-standard pattern).
|
|
64
|
+
*
|
|
65
|
+
* Request context is available via typed hooks created with createSSRHooks().
|
|
66
|
+
*
|
|
67
|
+
* @template TProps - The shape of props returned by the controller
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* // src/lib/ssr-hooks.ts
|
|
72
|
+
* import { createSSRHooks, RenderContext } from '@nestjs-ssr/react';
|
|
73
|
+
*
|
|
74
|
+
* interface AppRenderContext extends RenderContext {
|
|
75
|
+
* user?: User;
|
|
76
|
+
* }
|
|
77
|
+
*
|
|
78
|
+
* export const { usePageContext } = createSSRHooks<AppRenderContext>();
|
|
79
|
+
*
|
|
80
|
+
* // src/views/product.tsx
|
|
81
|
+
* import { usePageContext } from '@/lib/ssr-hooks';
|
|
82
|
+
*
|
|
83
|
+
* interface ProductPageProps {
|
|
84
|
+
* product: Product;
|
|
85
|
+
* relatedProducts: Product[];
|
|
86
|
+
* }
|
|
87
|
+
*
|
|
88
|
+
* export default function ProductDetail(props: PageProps<ProductPageProps>) {
|
|
89
|
+
* const { product, relatedProducts, head } = props;
|
|
90
|
+
* const context = usePageContext(); // Fully typed!
|
|
91
|
+
*
|
|
92
|
+
* return (
|
|
93
|
+
* <html>
|
|
94
|
+
* <head>
|
|
95
|
+
* <title>{head?.title || product.name}</title>
|
|
96
|
+
* </head>
|
|
97
|
+
* <body>
|
|
98
|
+
* <h1>{product.name}</h1>
|
|
99
|
+
* <p>Current path: {context.path}</p>
|
|
100
|
+
* </body>
|
|
101
|
+
* </html>
|
|
102
|
+
* );
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
type PageProps<TProps = {}> = TProps & {
|
|
107
|
+
/**
|
|
108
|
+
* Optional head metadata for SEO (title, description, og tags, etc.)
|
|
109
|
+
* Pass from controller to populate meta tags, Open Graph, etc.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* // In controller:
|
|
114
|
+
* return {
|
|
115
|
+
* product,
|
|
116
|
+
* head: {
|
|
117
|
+
* title: product.name,
|
|
118
|
+
* description: product.description,
|
|
119
|
+
* }
|
|
120
|
+
* };
|
|
121
|
+
*
|
|
122
|
+
* // In component:
|
|
123
|
+
* <head>
|
|
124
|
+
* <title>{props.head?.title}</title>
|
|
125
|
+
* <meta name="description" content={props.head?.description} />
|
|
126
|
+
* </head>
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
head?: HeadData;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Provider component that makes page context available to all child components.
|
|
134
|
+
* Should wrap the entire app in entry-server and entry-client.
|
|
135
|
+
*/
|
|
136
|
+
declare function PageContextProvider({ context, children, }: {
|
|
137
|
+
context: RenderContext;
|
|
138
|
+
children: React.ReactNode;
|
|
139
|
+
}): react_jsx_runtime.JSX.Element;
|
|
140
|
+
/**
|
|
141
|
+
* Factory function to create typed SSR hooks bound to your app's context type.
|
|
142
|
+
* Use this once in your app to create hooks with full type safety.
|
|
143
|
+
*
|
|
144
|
+
* This eliminates the need to pass generic types to every hook call,
|
|
145
|
+
* providing excellent DX with full IntelliSense support.
|
|
146
|
+
*
|
|
147
|
+
* @template T - Your extended RenderContext type with app-specific properties
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* // src/lib/ssr-hooks.ts - Define once
|
|
152
|
+
* import { createSSRHooks, RenderContext } from '@nestjs-ssr/react';
|
|
153
|
+
*
|
|
154
|
+
* interface AppRenderContext extends RenderContext {
|
|
155
|
+
* user?: {
|
|
156
|
+
* id: string;
|
|
157
|
+
* name: string;
|
|
158
|
+
* email: string;
|
|
159
|
+
* };
|
|
160
|
+
* tenant?: { id: string; name: string };
|
|
161
|
+
* featureFlags?: Record<string, boolean>;
|
|
162
|
+
* theme?: string; // From cookie
|
|
163
|
+
* }
|
|
164
|
+
*
|
|
165
|
+
* export const {
|
|
166
|
+
* usePageContext,
|
|
167
|
+
* useParams,
|
|
168
|
+
* useQuery,
|
|
169
|
+
* useRequest,
|
|
170
|
+
* useHeaders,
|
|
171
|
+
* useHeader,
|
|
172
|
+
* useCookies,
|
|
173
|
+
* useCookie,
|
|
174
|
+
* } = createSSRHooks<AppRenderContext>();
|
|
175
|
+
*
|
|
176
|
+
* // Create custom helper hooks
|
|
177
|
+
* export const useUser = () => usePageContext().user;
|
|
178
|
+
* export const useTheme = () => useCookie('theme');
|
|
179
|
+
* export const useUserAgent = () => useHeader('user-agent');
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* // src/views/home.tsx - Use everywhere with full types
|
|
185
|
+
* import { usePageContext, useUser, useTheme, useCookie, useHeader } from '@/lib/ssr-hooks';
|
|
186
|
+
*
|
|
187
|
+
* export default function Home() {
|
|
188
|
+
* const { user, featureFlags } = usePageContext(); // ✅ Fully typed!
|
|
189
|
+
* const user = useUser(); // ✅ Also typed!
|
|
190
|
+
* const theme = useTheme(); // ✅ From cookie
|
|
191
|
+
* const locale = useCookie('locale'); // ✅ Access specific cookie
|
|
192
|
+
* const tenantId = useHeader('x-tenant-id'); // ✅ Access specific header
|
|
193
|
+
*
|
|
194
|
+
* return (
|
|
195
|
+
* <div>
|
|
196
|
+
* <h1>Welcome {user?.name}</h1>
|
|
197
|
+
* <p>Theme: {theme}</p>
|
|
198
|
+
* <p>Locale: {locale}</p>
|
|
199
|
+
* <p>Tenant: {tenantId}</p>
|
|
200
|
+
* </div>
|
|
201
|
+
* );
|
|
202
|
+
* }
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
declare function createSSRHooks<T extends RenderContext = RenderContext>(): {
|
|
206
|
+
/**
|
|
207
|
+
* Hook to access the full page context with your app's type.
|
|
208
|
+
* Contains URL metadata, headers, and any custom properties you've added.
|
|
209
|
+
*/
|
|
210
|
+
usePageContext: () => T;
|
|
211
|
+
/**
|
|
212
|
+
* Hook to access route parameters.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```tsx
|
|
216
|
+
* // Route: /users/:id
|
|
217
|
+
* const params = useParams();
|
|
218
|
+
* console.log(params.id); // '123'
|
|
219
|
+
* ```
|
|
220
|
+
*/
|
|
221
|
+
useParams: () => Record<string, string>;
|
|
222
|
+
/**
|
|
223
|
+
* Hook to access query string parameters.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```tsx
|
|
227
|
+
* // URL: /search?q=react&sort=date
|
|
228
|
+
* const query = useQuery();
|
|
229
|
+
* console.log(query.q); // 'react'
|
|
230
|
+
* console.log(query.sort); // 'date'
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
useQuery: () => Record<string, string | string[]>;
|
|
234
|
+
/**
|
|
235
|
+
* Alias for usePageContext() with a more intuitive name.
|
|
236
|
+
* Returns the full request context with your app's type.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```tsx
|
|
240
|
+
* const request = useRequest();
|
|
241
|
+
* console.log(request.path); // '/users/123'
|
|
242
|
+
* console.log(request.method); // 'GET'
|
|
243
|
+
* console.log(request.params); // { id: '123' }
|
|
244
|
+
* console.log(request.query); // { search: 'foo' }
|
|
245
|
+
* ```
|
|
246
|
+
*/
|
|
247
|
+
useRequest: () => T;
|
|
248
|
+
/**
|
|
249
|
+
* Hook to access headers configured via allowedHeaders.
|
|
250
|
+
* Returns all headers as a Record.
|
|
251
|
+
*
|
|
252
|
+
* Configure in module registration:
|
|
253
|
+
* ```typescript
|
|
254
|
+
* RenderModule.register({
|
|
255
|
+
* allowedHeaders: ['user-agent', 'x-tenant-id', 'x-api-version']
|
|
256
|
+
* })
|
|
257
|
+
* ```
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```tsx
|
|
261
|
+
* const headers = useHeaders();
|
|
262
|
+
* console.log(headers['user-agent']); // 'Mozilla/5.0...'
|
|
263
|
+
* console.log(headers['x-tenant-id']); // 'tenant-123'
|
|
264
|
+
* console.log(headers['x-api-version']); // 'v2'
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
267
|
+
useHeaders: () => Record<string, string>;
|
|
268
|
+
/**
|
|
269
|
+
* Hook to access a specific custom header by name.
|
|
270
|
+
* Returns undefined if the header is not configured or not present.
|
|
271
|
+
*
|
|
272
|
+
* @param name - The header name (as configured in allowedHeaders)
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```tsx
|
|
276
|
+
* const tenantId = useHeader('x-tenant-id');
|
|
277
|
+
* if (tenantId) {
|
|
278
|
+
* console.log(`Tenant: ${tenantId}`);
|
|
279
|
+
* }
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
useHeader: (name: string) => string | undefined;
|
|
283
|
+
/**
|
|
284
|
+
* Hook to access cookies configured via allowedCookies.
|
|
285
|
+
* Returns all allowed cookies as a Record.
|
|
286
|
+
*
|
|
287
|
+
* Configure in module registration:
|
|
288
|
+
* ```typescript
|
|
289
|
+
* RenderModule.register({
|
|
290
|
+
* allowedCookies: ['theme', 'locale', 'consent']
|
|
291
|
+
* })
|
|
292
|
+
* ```
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```tsx
|
|
296
|
+
* const cookies = useCookies();
|
|
297
|
+
* console.log(cookies.theme); // 'dark'
|
|
298
|
+
* console.log(cookies.locale); // 'en-US'
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
useCookies: () => Record<string, string>;
|
|
302
|
+
/**
|
|
303
|
+
* Hook to access a specific cookie by name.
|
|
304
|
+
* Returns undefined if the cookie is not configured or not present.
|
|
305
|
+
*
|
|
306
|
+
* @param name - The cookie name (as configured in allowedCookies)
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```tsx
|
|
310
|
+
* const theme = useCookie('theme');
|
|
311
|
+
* if (theme === 'dark') {
|
|
312
|
+
* console.log('Dark mode enabled');
|
|
313
|
+
* }
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
useCookie: (name: string) => string | undefined;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
export { PageContextProvider, type PageProps, type RenderContext, createSSRHooks };
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { H as HeadData } from './render-response.interface-Dc-Kwb09.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Request context available to all React components.
|
|
7
|
+
* Contains safe request metadata that can be exposed to the client.
|
|
8
|
+
*
|
|
9
|
+
* Extend this interface to add app-specific properties (user, tenant, feature flags, etc.).
|
|
10
|
+
* Use module configuration to pass additional headers or cookies safely.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // Basic usage - use as-is
|
|
14
|
+
* const context: RenderContext = {
|
|
15
|
+
* url: '/users/123',
|
|
16
|
+
* path: '/users/123',
|
|
17
|
+
* query: { tab: 'profile' },
|
|
18
|
+
* params: { id: '123' },
|
|
19
|
+
* method: 'GET',
|
|
20
|
+
* };
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Extended usage - add custom properties for your app
|
|
24
|
+
* interface AppRenderContext extends RenderContext {
|
|
25
|
+
* user?: {
|
|
26
|
+
* id: string;
|
|
27
|
+
* name: string;
|
|
28
|
+
* email: string;
|
|
29
|
+
* roles: string[];
|
|
30
|
+
* };
|
|
31
|
+
* tenant?: {
|
|
32
|
+
* id: string;
|
|
33
|
+
* name: string;
|
|
34
|
+
* };
|
|
35
|
+
* featureFlags?: Record<string, boolean>;
|
|
36
|
+
* theme?: string; // From cookie
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* // Configure module to pass specific cookies/headers
|
|
40
|
+
* ReactSSRModule.forRoot({
|
|
41
|
+
* allowedCookies: ['theme', 'locale'],
|
|
42
|
+
* allowedHeaders: ['x-tenant-id'],
|
|
43
|
+
* })
|
|
44
|
+
*
|
|
45
|
+
* // Use in interceptor/controller
|
|
46
|
+
* const context: AppRenderContext = {
|
|
47
|
+
* ...baseContext,
|
|
48
|
+
* user: req.user,
|
|
49
|
+
* tenant: req.tenant,
|
|
50
|
+
* featureFlags: await featureFlagService.getFlags(req),
|
|
51
|
+
* };
|
|
52
|
+
*/
|
|
53
|
+
interface RenderContext {
|
|
54
|
+
url: string;
|
|
55
|
+
path: string;
|
|
56
|
+
query: Record<string, string | string[]>;
|
|
57
|
+
params: Record<string, string>;
|
|
58
|
+
method: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Generic type for React page component props.
|
|
63
|
+
* Spreads controller data directly as props (React-standard pattern).
|
|
64
|
+
*
|
|
65
|
+
* Request context is available via typed hooks created with createSSRHooks().
|
|
66
|
+
*
|
|
67
|
+
* @template TProps - The shape of props returned by the controller
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* // src/lib/ssr-hooks.ts
|
|
72
|
+
* import { createSSRHooks, RenderContext } from '@nestjs-ssr/react';
|
|
73
|
+
*
|
|
74
|
+
* interface AppRenderContext extends RenderContext {
|
|
75
|
+
* user?: User;
|
|
76
|
+
* }
|
|
77
|
+
*
|
|
78
|
+
* export const { usePageContext } = createSSRHooks<AppRenderContext>();
|
|
79
|
+
*
|
|
80
|
+
* // src/views/product.tsx
|
|
81
|
+
* import { usePageContext } from '@/lib/ssr-hooks';
|
|
82
|
+
*
|
|
83
|
+
* interface ProductPageProps {
|
|
84
|
+
* product: Product;
|
|
85
|
+
* relatedProducts: Product[];
|
|
86
|
+
* }
|
|
87
|
+
*
|
|
88
|
+
* export default function ProductDetail(props: PageProps<ProductPageProps>) {
|
|
89
|
+
* const { product, relatedProducts, head } = props;
|
|
90
|
+
* const context = usePageContext(); // Fully typed!
|
|
91
|
+
*
|
|
92
|
+
* return (
|
|
93
|
+
* <html>
|
|
94
|
+
* <head>
|
|
95
|
+
* <title>{head?.title || product.name}</title>
|
|
96
|
+
* </head>
|
|
97
|
+
* <body>
|
|
98
|
+
* <h1>{product.name}</h1>
|
|
99
|
+
* <p>Current path: {context.path}</p>
|
|
100
|
+
* </body>
|
|
101
|
+
* </html>
|
|
102
|
+
* );
|
|
103
|
+
* }
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
type PageProps<TProps = {}> = TProps & {
|
|
107
|
+
/**
|
|
108
|
+
* Optional head metadata for SEO (title, description, og tags, etc.)
|
|
109
|
+
* Pass from controller to populate meta tags, Open Graph, etc.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* // In controller:
|
|
114
|
+
* return {
|
|
115
|
+
* product,
|
|
116
|
+
* head: {
|
|
117
|
+
* title: product.name,
|
|
118
|
+
* description: product.description,
|
|
119
|
+
* }
|
|
120
|
+
* };
|
|
121
|
+
*
|
|
122
|
+
* // In component:
|
|
123
|
+
* <head>
|
|
124
|
+
* <title>{props.head?.title}</title>
|
|
125
|
+
* <meta name="description" content={props.head?.description} />
|
|
126
|
+
* </head>
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
head?: HeadData;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Provider component that makes page context available to all child components.
|
|
134
|
+
* Should wrap the entire app in entry-server and entry-client.
|
|
135
|
+
*/
|
|
136
|
+
declare function PageContextProvider({ context, children, }: {
|
|
137
|
+
context: RenderContext;
|
|
138
|
+
children: React.ReactNode;
|
|
139
|
+
}): react_jsx_runtime.JSX.Element;
|
|
140
|
+
/**
|
|
141
|
+
* Factory function to create typed SSR hooks bound to your app's context type.
|
|
142
|
+
* Use this once in your app to create hooks with full type safety.
|
|
143
|
+
*
|
|
144
|
+
* This eliminates the need to pass generic types to every hook call,
|
|
145
|
+
* providing excellent DX with full IntelliSense support.
|
|
146
|
+
*
|
|
147
|
+
* @template T - Your extended RenderContext type with app-specific properties
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```typescript
|
|
151
|
+
* // src/lib/ssr-hooks.ts - Define once
|
|
152
|
+
* import { createSSRHooks, RenderContext } from '@nestjs-ssr/react';
|
|
153
|
+
*
|
|
154
|
+
* interface AppRenderContext extends RenderContext {
|
|
155
|
+
* user?: {
|
|
156
|
+
* id: string;
|
|
157
|
+
* name: string;
|
|
158
|
+
* email: string;
|
|
159
|
+
* };
|
|
160
|
+
* tenant?: { id: string; name: string };
|
|
161
|
+
* featureFlags?: Record<string, boolean>;
|
|
162
|
+
* theme?: string; // From cookie
|
|
163
|
+
* }
|
|
164
|
+
*
|
|
165
|
+
* export const {
|
|
166
|
+
* usePageContext,
|
|
167
|
+
* useParams,
|
|
168
|
+
* useQuery,
|
|
169
|
+
* useRequest,
|
|
170
|
+
* useHeaders,
|
|
171
|
+
* useHeader,
|
|
172
|
+
* useCookies,
|
|
173
|
+
* useCookie,
|
|
174
|
+
* } = createSSRHooks<AppRenderContext>();
|
|
175
|
+
*
|
|
176
|
+
* // Create custom helper hooks
|
|
177
|
+
* export const useUser = () => usePageContext().user;
|
|
178
|
+
* export const useTheme = () => useCookie('theme');
|
|
179
|
+
* export const useUserAgent = () => useHeader('user-agent');
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```typescript
|
|
184
|
+
* // src/views/home.tsx - Use everywhere with full types
|
|
185
|
+
* import { usePageContext, useUser, useTheme, useCookie, useHeader } from '@/lib/ssr-hooks';
|
|
186
|
+
*
|
|
187
|
+
* export default function Home() {
|
|
188
|
+
* const { user, featureFlags } = usePageContext(); // ✅ Fully typed!
|
|
189
|
+
* const user = useUser(); // ✅ Also typed!
|
|
190
|
+
* const theme = useTheme(); // ✅ From cookie
|
|
191
|
+
* const locale = useCookie('locale'); // ✅ Access specific cookie
|
|
192
|
+
* const tenantId = useHeader('x-tenant-id'); // ✅ Access specific header
|
|
193
|
+
*
|
|
194
|
+
* return (
|
|
195
|
+
* <div>
|
|
196
|
+
* <h1>Welcome {user?.name}</h1>
|
|
197
|
+
* <p>Theme: {theme}</p>
|
|
198
|
+
* <p>Locale: {locale}</p>
|
|
199
|
+
* <p>Tenant: {tenantId}</p>
|
|
200
|
+
* </div>
|
|
201
|
+
* );
|
|
202
|
+
* }
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
declare function createSSRHooks<T extends RenderContext = RenderContext>(): {
|
|
206
|
+
/**
|
|
207
|
+
* Hook to access the full page context with your app's type.
|
|
208
|
+
* Contains URL metadata, headers, and any custom properties you've added.
|
|
209
|
+
*/
|
|
210
|
+
usePageContext: () => T;
|
|
211
|
+
/**
|
|
212
|
+
* Hook to access route parameters.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```tsx
|
|
216
|
+
* // Route: /users/:id
|
|
217
|
+
* const params = useParams();
|
|
218
|
+
* console.log(params.id); // '123'
|
|
219
|
+
* ```
|
|
220
|
+
*/
|
|
221
|
+
useParams: () => Record<string, string>;
|
|
222
|
+
/**
|
|
223
|
+
* Hook to access query string parameters.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```tsx
|
|
227
|
+
* // URL: /search?q=react&sort=date
|
|
228
|
+
* const query = useQuery();
|
|
229
|
+
* console.log(query.q); // 'react'
|
|
230
|
+
* console.log(query.sort); // 'date'
|
|
231
|
+
* ```
|
|
232
|
+
*/
|
|
233
|
+
useQuery: () => Record<string, string | string[]>;
|
|
234
|
+
/**
|
|
235
|
+
* Alias for usePageContext() with a more intuitive name.
|
|
236
|
+
* Returns the full request context with your app's type.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```tsx
|
|
240
|
+
* const request = useRequest();
|
|
241
|
+
* console.log(request.path); // '/users/123'
|
|
242
|
+
* console.log(request.method); // 'GET'
|
|
243
|
+
* console.log(request.params); // { id: '123' }
|
|
244
|
+
* console.log(request.query); // { search: 'foo' }
|
|
245
|
+
* ```
|
|
246
|
+
*/
|
|
247
|
+
useRequest: () => T;
|
|
248
|
+
/**
|
|
249
|
+
* Hook to access headers configured via allowedHeaders.
|
|
250
|
+
* Returns all headers as a Record.
|
|
251
|
+
*
|
|
252
|
+
* Configure in module registration:
|
|
253
|
+
* ```typescript
|
|
254
|
+
* RenderModule.register({
|
|
255
|
+
* allowedHeaders: ['user-agent', 'x-tenant-id', 'x-api-version']
|
|
256
|
+
* })
|
|
257
|
+
* ```
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ```tsx
|
|
261
|
+
* const headers = useHeaders();
|
|
262
|
+
* console.log(headers['user-agent']); // 'Mozilla/5.0...'
|
|
263
|
+
* console.log(headers['x-tenant-id']); // 'tenant-123'
|
|
264
|
+
* console.log(headers['x-api-version']); // 'v2'
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
267
|
+
useHeaders: () => Record<string, string>;
|
|
268
|
+
/**
|
|
269
|
+
* Hook to access a specific custom header by name.
|
|
270
|
+
* Returns undefined if the header is not configured or not present.
|
|
271
|
+
*
|
|
272
|
+
* @param name - The header name (as configured in allowedHeaders)
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```tsx
|
|
276
|
+
* const tenantId = useHeader('x-tenant-id');
|
|
277
|
+
* if (tenantId) {
|
|
278
|
+
* console.log(`Tenant: ${tenantId}`);
|
|
279
|
+
* }
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
useHeader: (name: string) => string | undefined;
|
|
283
|
+
/**
|
|
284
|
+
* Hook to access cookies configured via allowedCookies.
|
|
285
|
+
* Returns all allowed cookies as a Record.
|
|
286
|
+
*
|
|
287
|
+
* Configure in module registration:
|
|
288
|
+
* ```typescript
|
|
289
|
+
* RenderModule.register({
|
|
290
|
+
* allowedCookies: ['theme', 'locale', 'consent']
|
|
291
|
+
* })
|
|
292
|
+
* ```
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```tsx
|
|
296
|
+
* const cookies = useCookies();
|
|
297
|
+
* console.log(cookies.theme); // 'dark'
|
|
298
|
+
* console.log(cookies.locale); // 'en-US'
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
useCookies: () => Record<string, string>;
|
|
302
|
+
/**
|
|
303
|
+
* Hook to access a specific cookie by name.
|
|
304
|
+
* Returns undefined if the cookie is not configured or not present.
|
|
305
|
+
*
|
|
306
|
+
* @param name - The cookie name (as configured in allowedCookies)
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```tsx
|
|
310
|
+
* const theme = useCookie('theme');
|
|
311
|
+
* if (theme === 'dark') {
|
|
312
|
+
* console.log('Dark mode enabled');
|
|
313
|
+
* }
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
useCookie: (name: string) => string | undefined;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
export { PageContextProvider, type PageProps, type RenderContext, createSSRHooks };
|