@shadow-library/fastify 1.0.0 → 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 +90 -1
- package/cjs/module/fastify-module.interface.d.ts +6 -0
- package/cjs/module/fastify-router.d.ts +1 -1
- package/cjs/module/fastify-router.js +4 -2
- package/cjs/module/fastify.module.js +1 -1
- package/esm/module/fastify-module.interface.d.ts +6 -0
- package/esm/module/fastify-router.d.ts +1 -1
- package/esm/module/fastify-router.js +4 -2
- package/esm/module/fastify.module.js +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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) {
|
|
@@ -65,7 +65,7 @@ let FastifyModule = FastifyModule_1 = class FastifyModule {
|
|
|
65
65
|
providers.push({ token: constants_1.FASTIFY_INSTANCE, useFactory: fastifyFactory, inject: [constants_1.FASTIFY_CONFIG] });
|
|
66
66
|
if (options.providers)
|
|
67
67
|
providers.push(...options.providers);
|
|
68
|
-
const exports = [app_1.Router, services_1.ContextService];
|
|
68
|
+
const exports = [app_1.Router, services_1.ContextService, constants_1.FASTIFY_INSTANCE];
|
|
69
69
|
if (options.exports)
|
|
70
70
|
exports.push(...options.exports);
|
|
71
71
|
const Module = { module: FastifyModule_1, providers, exports };
|
|
@@ -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
|
|
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) {
|
|
@@ -62,7 +62,7 @@ let FastifyModule = FastifyModule_1 = class FastifyModule {
|
|
|
62
62
|
providers.push({ token: FASTIFY_INSTANCE, useFactory: fastifyFactory, inject: [FASTIFY_CONFIG] });
|
|
63
63
|
if (options.providers)
|
|
64
64
|
providers.push(...options.providers);
|
|
65
|
-
const exports = [Router, ContextService];
|
|
65
|
+
const exports = [Router, ContextService, FASTIFY_INSTANCE];
|
|
66
66
|
if (options.exports)
|
|
67
67
|
exports.push(...options.exports);
|
|
68
68
|
const Module = { module: FastifyModule_1, providers, exports };
|
package/package.json
CHANGED