Skip to content

Commit 5bc7a23

Browse files
committed
feat(platform-fastify): implement lazy middleware registration
1 parent d602f74 commit 5bc7a23

File tree

2 files changed

+38
-24
lines changed

2 files changed

+38
-24
lines changed

integration/hello-world/e2e/fastify-middleware-before-init.spec.ts

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe('Middleware before init (FastifyAdapter)', () => {
5353
}
5454
}
5555

56-
describe('should throw helpful error when middleware is registered before init', () => {
56+
describe('should queue middleware when registered before init', () => {
5757
beforeEach(async () => {
5858
const module = await Test.createTestingModule({
5959
imports: [TestModule],
@@ -63,23 +63,34 @@ describe('Middleware before init (FastifyAdapter)', () => {
6363
new FastifyAdapter(),
6464
);
6565

66-
// This should throw a helpful error message
67-
let errorMessage = '';
68-
try {
69-
app.use((req, res, next) => {
70-
req.headers['x-global-middleware'] = 'applied';
71-
next();
72-
});
73-
} catch (error) {
74-
errorMessage = error.message;
75-
}
66+
// Register middleware before init - should be queued
67+
app.use((req, res, next) => {
68+
req.headers['x-global-middleware'] = 'applied';
69+
next();
70+
});
71+
72+
// Now init the app - queued middleware should be registered
73+
await app.init();
74+
await app.getHttpAdapter().getInstance().ready();
75+
});
7676

77-
expect(errorMessage).to.equal('this.instance.use is not a function');
78-
// The helpful error message is logged, not thrown
77+
it('should apply queued middleware after init', () => {
78+
return app
79+
.inject({
80+
method: 'GET',
81+
url: '/test',
82+
})
83+
.then(({ statusCode, payload, headers }) => {
84+
expect(statusCode).to.equal(200);
85+
expect(JSON.parse(payload)).to.deep.equal({ data: 'test_data' });
86+
// Verify both module-level and global middleware were applied
87+
expect(headers['x-middleware']).to.equal('applied');
88+
expect(headers['x-global-middleware']).to.equal('applied');
89+
});
7990
});
8091

81-
it('should display clear error message', () => {
82-
// Test is complete in beforeEach
92+
afterEach(async () => {
93+
await app.close();
8394
});
8495
});
8596

packages/platform-fastify/adapters/fastify-adapter.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ export class FastifyAdapter<
146146

147147
private _isParserRegistered: boolean;
148148
private isMiddieRegistered: boolean;
149+
private pendingMiddlewares: Array<{ args: any[] }> = [];
149150
private versioningOptions?: VersioningOptions;
150151
private readonly versionConstraint = {
151152
name: 'version',
@@ -256,6 +257,14 @@ export class FastifyAdapter<
256257
return;
257258
}
258259
await this.registerMiddie();
260+
261+
// Register any pending middlewares that were added before init
262+
if (this.pendingMiddlewares.length > 0) {
263+
for (const { args } of this.pendingMiddlewares) {
264+
super.use(...args);
265+
}
266+
this.pendingMiddlewares = [];
267+
}
259268
}
260269

261270
public listen(port: string | number, callback?: () => void): void;
@@ -672,16 +681,10 @@ export class FastifyAdapter<
672681

673682
public use(...args: any[]) {
674683
// Fastify requires @fastify/middie plugin to be registered before middleware can be used.
675-
// Unlike Express, middleware registration in Fastify must happen after initialization.
676-
// We provide a helpful error message to guide developers to call app.init() first.
684+
// If middie is not registered yet, we queue the middleware and register it later during init.
677685
if (!this.isMiddieRegistered) {
678-
Logger.warn(
679-
'Middleware registration requires the "@fastify/middie" plugin to be registered first. ' +
680-
'Make sure to call app.init() before registering middleware with the Fastify adapter. ' +
681-
'See https://github.com/nestjs/nest/issues/15310 for more details.',
682-
FastifyAdapter.name,
683-
);
684-
throw new TypeError('this.instance.use is not a function');
686+
this.pendingMiddlewares.push({ args });
687+
return this;
685688
}
686689
return super.use(...args);
687690
}

0 commit comments

Comments
 (0)