Seanyboy Lee
Seanyboy Lee

Reputation: 195

How to reference the app instance in a module in Nest.js

I'm working on a project that's using multiple Nest repos, around 4. Every repo needs to implementing logging to log things like

Ideally, I'd like to package everything up into a module which I can publish to my company's NPM organization and just consume directly in each of my projects. That way, it would take very minimal code to get logging set up in each project.

One of the things I'd like to log in my server lifecycle event is the server's url. I know you can get this via app.getUrl() in the bootstrapping phase, but it would be great to have access to the app instance in a module's lifecycle hook like so.

@Module({})
export class LoggingModule implements NestModule {
  onApplicationBootstrap() {
    console.log(`Server started on ${app.getUrl()}`)
  }
  beforeApplicationShutdown() {
    console.log('shutting down')
  }
  onApplicationShutdown() {
    console.log('successfully shut down')
  }
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggingMiddleware).forRoutes('*')
  }
}

Is this possible?

Upvotes: 5

Views: 11824

Answers (3)

Papooch
Papooch

Reputation: 1645

Ï thought I'd chime in and offer one of the hacky solutions. Only use this, if there is absolutely no other way or your deadline is coming in an hour.

Create a class that can hold the application instance

export class AppHost {
  app: INestApplication
}

And a module to host it

@Module({
  providers: [AppHost]
  exports: [AppHost]
})
export class AppHostModule {}

In your bootstrap() function, retrieve the AppHost instance and assign the app itself

// after NestFactory.create() ...
app.select(AppHostModule).get(AppHost).app = app;

Now, the actual application will be available wherever you inject AppHost.

Be aware, though, that the app will not be available inside AppHost before the whole application bootstraps (in onModuleInit, onApplicationBootstrap hooks or in provider factories), but it should be available in shutdown hooks.

Upvotes: 4

estani
estani

Reputation: 26527

Not sure is that hacky... I'm using this to prevent the server from starting in case of pending migrations.

// AppModule.ts
export class AppModule implements NestModule {
  app: INestApplication;

  async configure(consumer: MiddlewareConsumer) {
    if (await this.hasPendingMigrations()) {
      setTimeout(()=> {
        this.logger.error("There are pending migrations!")
        process.exitCode = 1;
        this.app.close();
      }, 1000);
    }
    //...
  }

  public setApp(app: INestApplication) {
    this.app = app;
  }

  //...
}

//main.ts
const app = await NestFactory.create(AppModule, {
  logger: config.cfgServer.logger,
});
app.get(AppModule).setApp(app);

Upvotes: 4

Micael Levi
Micael Levi

Reputation: 6695

There's no way (besides hacky ones, maybe) to access the app itself inside modules.

As you can see here, app.getUrl() uses the underlying HTTP server. Thus I guess you can retrieve the same data using the provider HttpAdapterHost.

Upvotes: 4

Related Questions