From 4063cdb5d75ad68a4780f66fe0bfb7ce7bd4b55a Mon Sep 17 00:00:00 2001 From: Oleh Strokan Date: Wed, 27 May 2026 18:58:42 +0200 Subject: [PATCH] feat(microservices): expose transport server getter --- packages/common/index.ts | 1 + packages/common/interfaces/index.ts | 1 + .../transport-server.interface.ts | 19 +++++++++++++++++++ .../interfaces/nest-microservice.interface.ts | 8 ++++++++ packages/microservices/nest-microservice.ts | 10 ++++++++++ packages/microservices/server/server.ts | 4 ++-- .../test/nest-microservice.spec.ts | 18 ++++++++++++++++++ 7 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 packages/common/interfaces/microservices/transport-server.interface.ts diff --git a/packages/common/index.ts b/packages/common/index.ts index fa9aac3727b..c8a55c86b17 100644 --- a/packages/common/index.ts +++ b/packages/common/index.ts @@ -32,6 +32,7 @@ export { INestApplication, INestApplicationContext, INestMicroservice, + ITransportServer, InjectionToken, IntrospectionResult, MessageEvent, diff --git a/packages/common/interfaces/index.ts b/packages/common/interfaces/index.ts index 792a448fe89..a40b90cdf1a 100644 --- a/packages/common/interfaces/index.ts +++ b/packages/common/interfaces/index.ts @@ -18,6 +18,7 @@ export * from './http/index.js'; export * from './injectable.interface.js'; export * from './microservices/nest-hybrid-application-options.interface.js'; export * from './microservices/pre-request-hook.interface.js'; +export * from './microservices/transport-server.interface.js'; export * from './middleware/index.js'; export * from './modules/index.js'; export * from './nest-application-context.interface.js'; diff --git a/packages/common/interfaces/microservices/transport-server.interface.ts b/packages/common/interfaces/microservices/transport-server.interface.ts new file mode 100644 index 00000000000..fba3536bb31 --- /dev/null +++ b/packages/common/interfaces/microservices/transport-server.interface.ts @@ -0,0 +1,19 @@ +/** + * Interface describing the shape of a transport server. + * Used as the return type of `getTransportServer()` to provide + * autocomplete without creating circular dependencies. + * + * @publicApi + */ +export interface ITransportServer { + /** + * Starts the transport server. + * @param callback Function to be called upon initialization + */ + listen(callback: (...optionalParams: unknown[]) => any): any; + + /** + * Closes the transport server (stops listening on port/connection). + */ + close(): any; +} diff --git a/packages/common/interfaces/nest-microservice.interface.ts b/packages/common/interfaces/nest-microservice.interface.ts index 742f192dabb..775f67b2cae 100644 --- a/packages/common/interfaces/nest-microservice.interface.ts +++ b/packages/common/interfaces/nest-microservice.interface.ts @@ -3,6 +3,7 @@ import { ExceptionFilter } from './exceptions/exception-filter.interface.js'; import { CanActivate } from './features/can-activate.interface.js'; import { NestInterceptor } from './features/nest-interceptor.interface.js'; import { PipeTransform } from './features/pipe-transform.interface.js'; +import { ITransportServer } from './microservices/transport-server.interface.js'; import { PreRequestHook } from './microservices/pre-request-hook.interface.js'; import { INestApplicationContext } from './nest-application-context.interface.js'; import { WebSocketAdapter } from './websockets/web-socket-adapter.interface.js'; @@ -99,4 +100,11 @@ export interface INestMicroservice extends INestApplicationContext { * or a group of servers if there are more than one. */ unwrap(): T; + + /** + * Returns the underlying transport server instance. + * Use this to close only the transport (port/connection) without + * triggering the full application shutdown lifecycle. + */ + getTransportServer(): ITransportServer; } diff --git a/packages/microservices/nest-microservice.ts b/packages/microservices/nest-microservice.ts index 7d94f2229e6..0b310c8cdad 100644 --- a/packages/microservices/nest-microservice.ts +++ b/packages/microservices/nest-microservice.ts @@ -2,6 +2,7 @@ import type { CanActivate, ExceptionFilter, INestMicroservice, + ITransportServer, NestInterceptor, PipeTransform, PreRequestHook, @@ -359,6 +360,15 @@ export class NestMicroservice throw new Error('"unwrap" method not supported by the underlying server'); } + /** + * Returns the underlying transport server instance. + * Use this to close only the transport (port/connection) without + * triggering the full application shutdown lifecycle. + */ + public getTransportServer(): ITransportServer { + return this.serverInstance; + } + protected async closeApplication(): Promise { this.socketModule && (await this.socketModule.close()); this.microservicesModule && (await this.microservicesModule.close()); diff --git a/packages/microservices/server/server.ts b/packages/microservices/server/server.ts index d035b5cdb22..519b771c314 100644 --- a/packages/microservices/server/server.ts +++ b/packages/microservices/server/server.ts @@ -38,7 +38,7 @@ import { import { ConsumerSerializer } from '../interfaces/serializer.interface.js'; import { IdentitySerializer } from '../serializers/identity.serializer.js'; import { transformPatternToRoute } from '../utils/index.js'; -import { Logger, type LoggerService } from '@nestjs/common'; +import { ITransportServer, Logger, type LoggerService } from '@nestjs/common'; import { loadPackage, loadPackageSync } from '@nestjs/common/internal'; /** @@ -47,7 +47,7 @@ import { loadPackage, loadPackageSync } from '@nestjs/common/internal'; export abstract class Server< EventsMap extends Record = Record, Status extends string = string, -> { +> implements ITransportServer { /** * Unique transport identifier. */ diff --git a/packages/microservices/test/nest-microservice.spec.ts b/packages/microservices/test/nest-microservice.spec.ts index 8ddc026bf9b..729745a55c6 100644 --- a/packages/microservices/test/nest-microservice.spec.ts +++ b/packages/microservices/test/nest-microservice.spec.ts @@ -214,4 +214,22 @@ describe('NestMicroservice', () => { expect(result).toBe(instance); }); }); + + it('should return the transport server instance via getTransportServer()', () => { + const strategy = new (class extends Server { + listen = vi.fn(); + close = vi.fn(); + on = vi.fn(); + unwrap = vi.fn(); + })(); + + const instance = new NestMicroservice( + mockContainer, + { strategy }, + mockGraphInspector, + mockAppConfig, + ); + + expect(instance.getTransportServer()).toBe(strategy); + }); });