@shadow-library/fastify 1.0.1 → 1.1.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.
package/README.md CHANGED
@@ -223,6 +223,89 @@ export class RoutesController {
223
223
  }
224
224
  ```
225
225
 
226
+ #### Child Routes Configuration
227
+
228
+ Child routes enable server-side route resolution, commonly used for SSR (Server-Side Rendering) and internal API composition. When enabled, you can make internal HTTP requests to your own routes without going through the network layer.
229
+
230
+ **Basic Setup:**
231
+
232
+ ```typescript
233
+ @Module({
234
+ imports: [
235
+ FastifyModule.forRoot({
236
+ controllers: [UserController, DataController],
237
+
238
+ // Enable child routes functionality
239
+ enableChildRoutes: true,
240
+
241
+ // Optional: Provide custom headers for child route requests
242
+ childRouteHeaders: () => ({
243
+ 'x-correlation-id': '123',
244
+ }),
245
+ }),
246
+ ],
247
+ })
248
+ export class AppModule {}
249
+ ```
250
+
251
+ **Usage in Controllers:**
252
+
253
+ ```typescript
254
+ @HttpController('/api')
255
+ export class DataAggregatorController {
256
+ constructor(@Inject(Router) private readonly fastifyRouter: FastifyRouter) {}
257
+
258
+ @Get('/dashboard')
259
+ async getDashboardData() {
260
+ // Make internal requests to other routes
261
+ const [users, posts, analytics] = await Promise.all([
262
+ this.fastifyRouter.resolveChildRoute('/api/users'),
263
+ this.fastifyRouter.resolveChildRoute('/api/posts?limit=10'),
264
+ this.fastifyRouter.resolveChildRoute('/api/analytics/summary'),
265
+ ]);
266
+
267
+ return {
268
+ dashboard: {
269
+ users,
270
+ posts,
271
+ analytics,
272
+ timestamp: new Date().toISOString(),
273
+ },
274
+ };
275
+ }
276
+ }
277
+ ```
278
+
279
+ **Custom Headers Function:**
280
+
281
+ The `childRouteHeaders` function is called for each child route request, allowing you to:
282
+
283
+ - Pass authentication context from the parent request
284
+ - Include tenant/user-specific information
285
+ - Add tracing or correlation IDs
286
+ - Set internal service flags
287
+
288
+ ```typescript
289
+ // Dynamic headers based on current request context
290
+ childRouteHeaders: (contextService) => {
291
+ const request = contextService.getRequest();
292
+ return {
293
+ 'x-user-id': contextService.get('currentUserId'),
294
+ 'x-request-id': contextService.getRID(),
295
+ 'x-forwarded-from': 'internal-aggregator',
296
+ 'x-correlation-id': request.headers['x-correlation-id'],
297
+ };
298
+ },
299
+ ```
300
+
301
+ **Important Notes:**
302
+
303
+ - Child routes always include the header `x-service: 'internal-child-route'`
304
+ - Custom headers are merged with the default service header
305
+ - If you provide an `x-service` header, it will be overridden with the default value
306
+ - Child routes create isolated contexts, preventing middleware conflicts
307
+ - Enable only when needed, as it adds routing overhead
308
+
226
309
  ## Configuration
227
310
 
228
311
  ### Dynamic Module Configuration
@@ -269,6 +352,12 @@ The module provides two configuration methods:
269
352
  '5xx': ErrorResponseSchema,
270
353
  },
271
354
 
355
+ // Child routes configuration (for SSR and internal route resolution)
356
+ enableChildRoutes: true,
357
+ childRouteHeaders: contextService => ({
358
+ 'x-correlation-id': contextService.getRequest().headers['x-correlation-id'],
359
+ }),
360
+
272
361
  // Extend Fastify instance before registering controllers
273
362
  fastifyFactory: async fastify => {
274
363
  // Register plugins, add hooks, or configure Fastify
@@ -800,7 +889,7 @@ Check out the [examples](./examples) directory for complete working examples:
800
889
 
801
890
  - **hello-world**: Basic HTTP controller with GET/POST routes
802
891
  - **user-auth**: Advanced example with authentication guards
803
- - **child-routes**: Route resolution and unified endpoints
892
+ - **child-routes**: Route resolution, unified endpoints, and custom headers for SSR
804
893
 
805
894
  ## Contributing
806
895
 
@@ -9,6 +9,7 @@ import { Promisable } from 'type-fest';
9
9
  * Importing user defined packages
10
10
  */
11
11
  import { ErrorHandler } from '../interfaces/index.js';
12
+ import { ContextService } from '../services/index.js';
12
13
  /**
13
14
  * Defining types
14
15
  */
@@ -39,6 +40,11 @@ export interface FastifyConfig extends FastifyServerOptions {
39
40
  * @default false
40
41
  */
41
42
  enableChildRoutes?: boolean;
43
+ /**
44
+ * Function to provide custom headers for internal child route requests.
45
+ * Useful for passing authentication tokens or other necessary headers.
46
+ */
47
+ childRouteHeaders?: (contextService: ContextService) => Record<string, string>;
42
48
  /**
43
49
  * Masks fields marked as sensitive in API inputs (body, query, and URL params) when written to logs.
44
50
  * @default true
@@ -82,7 +82,7 @@ export declare class FastifyRouter extends Router {
82
82
  * during SSR. Automatically reuses middleware results from the parent context to avoid
83
83
  * redundant execution and ensures correct context isolation for nested route data fetching.
84
84
  */
85
- resolveChildRoute<T extends JsonValue = JsonObject>(url: string): Promise<T>;
85
+ resolveChildRoute<T extends JsonValue = JsonObject>(url: string, headers?: Record<string, string>): Promise<T>;
86
86
  mockRequest(): MockRequestChain;
87
87
  mockRequest(options: MockRequestOptions): Promise<MockResponse>;
88
88
  }
@@ -285,10 +285,12 @@ let FastifyRouter = class FastifyRouter extends app_1.Router {
285
285
  * during SSR. Automatically reuses middleware results from the parent context to avoid
286
286
  * redundant execution and ensures correct context isolation for nested route data fetching.
287
287
  */
288
- async resolveChildRoute(url) {
288
+ async resolveChildRoute(url, headers = {}) {
289
289
  if (!this.childRouter)
290
290
  throw new common_1.InternalError('Child routes are not enabled');
291
- const response = await this.instance.inject({ method: 'GET', url, headers: { 'x-service': 'internal-child-route' } });
291
+ const childHeaders = this.config.childRouteHeaders?.(this.context) ?? {};
292
+ Object.assign(headers, childHeaders, { 'x-service': 'internal-child-route' });
293
+ const response = await this.instance.inject({ method: 'GET', url, headers });
292
294
  return response.json();
293
295
  }
294
296
  mockRequest(options) {
@@ -9,6 +9,7 @@ import { Promisable } from 'type-fest';
9
9
  * Importing user defined packages
10
10
  */
11
11
  import { ErrorHandler } from '../interfaces/index.js';
12
+ import { ContextService } from '../services/index.js';
12
13
  /**
13
14
  * Defining types
14
15
  */
@@ -39,6 +40,11 @@ export interface FastifyConfig extends FastifyServerOptions {
39
40
  * @default false
40
41
  */
41
42
  enableChildRoutes?: boolean;
43
+ /**
44
+ * Function to provide custom headers for internal child route requests.
45
+ * Useful for passing authentication tokens or other necessary headers.
46
+ */
47
+ childRouteHeaders?: (contextService: ContextService) => Record<string, string>;
42
48
  /**
43
49
  * Masks fields marked as sensitive in API inputs (body, query, and URL params) when written to logs.
44
50
  * @default true
@@ -82,7 +82,7 @@ export declare class FastifyRouter extends Router {
82
82
  * during SSR. Automatically reuses middleware results from the parent context to avoid
83
83
  * redundant execution and ensures correct context isolation for nested route data fetching.
84
84
  */
85
- resolveChildRoute<T extends JsonValue = JsonObject>(url: string): Promise<T>;
85
+ resolveChildRoute<T extends JsonValue = JsonObject>(url: string, headers?: Record<string, string>): Promise<T>;
86
86
  mockRequest(): MockRequestChain;
87
87
  mockRequest(options: MockRequestOptions): Promise<MockResponse>;
88
88
  }
@@ -279,10 +279,12 @@ let FastifyRouter = class FastifyRouter extends Router {
279
279
  * during SSR. Automatically reuses middleware results from the parent context to avoid
280
280
  * redundant execution and ensures correct context isolation for nested route data fetching.
281
281
  */
282
- async resolveChildRoute(url) {
282
+ async resolveChildRoute(url, headers = {}) {
283
283
  if (!this.childRouter)
284
284
  throw new InternalError('Child routes are not enabled');
285
- const response = await this.instance.inject({ method: 'GET', url, headers: { 'x-service': 'internal-child-route' } });
285
+ const childHeaders = this.config.childRouteHeaders?.(this.context) ?? {};
286
+ Object.assign(headers, childHeaders, { 'x-service': 'internal-child-route' });
287
+ const response = await this.instance.inject({ method: 'GET', url, headers });
286
288
  return response.json();
287
289
  }
288
290
  mockRequest(options) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shadow-library/fastify",
3
3
  "type": "module",
4
- "version": "1.0.1",
4
+ "version": "1.1.0",
5
5
  "sideEffects": false,
6
6
  "description": "A Fastify wrapper featuring decorator-based routing, middleware and error handling",
7
7
  "repository": {