I believe that the way Nestjs is bootstraped could be improved by allowing the definition of the container before the definition of the application.
Take as an example a ConfigService that would read all the variables in .env in order to use them as options to define a new Nestjs Microservice while having the following code, how would you do it?
async function bootstrap() {
const app = await NestFactory.createMicroservice(AppModule, {
transport: Transport.RMQ,
options: {
urls: [
'amqp://guest:guest@localhost:5672',
],
queue: 'test',
queueOptions: { durable: true },
},
});
...
}
At the moment only 2 solutions come in mind:
ApplicationContext to be able to get the ConfigService from the container to use it for instantiating the microservice.DependencyInjectionI believe that this could be done by instantiating the ApplicationContext that loads up the Container and then use the ApplicationContext as a parameter for the NestFactory.createMicroservice method.
In order to support backwards compatibility you could even allow both the current way in case the paramenter a Module or the following one in case it is an instance of an ApplicationContext
async function bootstrap() {
const app = await NestFactory.createApplicationContext(AppModule);
const config = app.get(ConfigService);
const microservice = await NestFactory.createMicroservice(app, {
transport: Transport.RMQ,
options: {
urls: [
config.amqpUrl,
],
queue: config.queue,
queueOptions: { durable: true },
},
});
...
}
LoggerService via DependecyInjection and also allow setting config options on it in order to call external services like Logstash etc.@kamilmysliwiec is this a planned feature?
I found this solution ->
const app = await NestFactory.create(AppModule, {
logger: new Logger(),
})
const configService = app.get<ConfigService>(ConfigService)
app.connectMicroservice<MicroserviceOptions>({
transport: Transport.RMQ,
options: {
urls: [amqp://${configService.get<string>('rabbitmq.host')}:${configService.get<number>
('rabbitmq.port')}],
queue: 'authentication',
queueOptions: {
durable: false,
},
},
})
app.startAllMicroservices(() => {
logger.log('Microservice is listening...')
})
this is work (usual MICROSERVICES) ! but this appear not work for websockets
I`m implementing Nest.js powered microservice and I need to do two things. Firstly, I need to get a configuration service in my main.ts file, and pass it as a constructor param to a custom transport strategy. Secondly, I need to do some bootstrapping actions in my service after microservice was bootstrapped.
The issue I faced seems related to this issue: when I`m using app = await NestFactory.create(AppModule) and then app.connectMicroservice({strategy: myCustomStrategy}) - _onApplicationBootstrap_ event has not fired. But when I`m using appContext = await NestFactory.createApplicationContext(AppModule) and then microservice = await NestFactory.createMicroservice(appContext, {strategy: myCustomStrategy}) - there is an error 'metatype is not a constructor' raised at _NestFactoryStatic.createMicroservice._
So for now I don`t understand, how I can pass correct environment config and catch the bootstrapping event simultaneously. Please, help me to figure out, if it can be done somehow.
I found this solution ->
const app = await NestFactory.create(AppModule, { logger: new Logger(), }) const configService = app.get<ConfigService>(ConfigService) app.connectMicroservice<MicroserviceOptions>({ transport: Transport.RMQ, options: { urls: [amqp://${configService.get<string>('rabbitmq.host')}:${configService.get<number> ('rabbitmq.port')}], queue: 'authentication', queueOptions: { durable: false, }, }, }) app.startAllMicroservices(() => { logger.log('Microservice is listening...') })this is work (usual MICROSERVICES) ! but this appear not work for websockets
The one bit that becomes a sticking point with this example is that lifecycle methods do not work.
I found this solution ->
const app = await NestFactory.create(AppModule, { logger: new Logger(), }) const configService = app.get<ConfigService>(ConfigService) app.connectMicroservice<MicroserviceOptions>({ transport: Transport.RMQ, options: { urls: [amqp://${configService.get<string>('rabbitmq.host')}:${configService.get<number> ('rabbitmq.port')}], queue: 'authentication', queueOptions: { durable: false, }, }, }) app.startAllMicroservices(() => { logger.log('Microservice is listening...') })this is work (usual MICROSERVICES) ! but this appear not work for websockets
The one bit that becomes a sticking point with this example is that lifecycle methods do not work.
Yes, but you can call the app.init method manually
app.startAllMicroservices(async () => {
// Calls the Nest lifecycle events.
await app.init()
logger.log('Microservice is listening...')
})
Is this gonna be solved or stay this way with the current workarounds, in my opinion this is pretty trivial usage
Most helpful comment
@kamilmysliwiec is this a planned feature?