Proper way to export dynamic module - node.js

I have a NestJS application with the CoreModule which exports an collection of the core services to all other modules.
In core module i have dynamic module register HttpModule.
I won't to register this module twice for import and export so i do the following:
const httpModule = HttpModule.register({
timeout: Configuration.requestTimeoutMilliseconds
});
#Module({
imports: [httpModule],
providers: [
...
],
exports: [
httpModule,
...
]
})
export class CoreModule { }
When i start my app i see in InstanceLoader logs HttpModule dependencies registered twice:
What the proper way to export dynamic modules in general?

You can do it like this.
#Module({
imports: [
HttpModule.register({
timeout: Configuration.requestTimeoutMilliseconds,
}),
],
providers: [],
exports: [HttpModule],
})
export class CoreModule {}
Makes sense to me because when you want to implement a dynamic module, you need to return module class as a module identifier in the module field.
There are examples of declaring dynamic modules on this page in documentation https://docs.nestjs.com/fundamentals/dynamic-modules#module-configuration

Related

NestJS - Export Custom Factory Provider (useFactory)

I have created a custom provider in one of my modules.
I need to export that custom provider to make it available in other modules and I'm having trouble doing so. I do not know what to put in the exports array.
Below is my custom provider.
#Module({
imports: [TypeOrmModule.forFeature([TypeOrmUser])],
providers: [
UserMapper,
UserService,
{
provide: getRepositoryToken(TypeOrmUser),
inject: [getDataSourceToken()],
useFactory(dataSource: DataSource) {
return dataSource.getRepository(TypeOrmUser).extend(userRepositoryImpl);
},
},
],
exports: [UserService, 'what to put here to export custom user repository?'],
})
export class UsersModule {}
Thank you for your help.
To export a custom provider, all that is needed to be added to the exports array is the provider's injection token.
In this case, that's getRepositoryToken(TypeOrmUser)
You can export it either with token name, or with the whole provider object. In your case it would be something like this:
exports: [UserService, getRepositoryToken(TypeOrmUser)],
or:
const customProvider = {
provide: getRepositoryToken(TypeOrmUser),
inject: [getDataSourceToken()],
useFactory(dataSource: DataSource) {
return dataSource.getRepository(TypeOrmUser).extend(userRepositoryImpl);
},
};
#Module({
imports: [TypeOrmModule.forFeature([TypeOrmUser])],
providers: [
UserMapper,
UserService,
customProvider,
],
exports: [UserService, customProvider],
})

Nest can't resolve dependencies of the DiscoveryService (?). Please make sure that the argument ModulesContainer at index [0] is available in

In a NestJs project, I created a module that uses, DiscoveryService in the services. It working fine. I wanted to create a nest library from that module. I followed this nestJs documentation then I am getting the below error. I tried both adding ModulesContainer in to my module imports and providers. nothing helped.
[Nest] 65775 - 10/12/2022, 11:55:03 AM ERROR [ExceptionHandler] Nest can't resolve dependencies of the DiscoveryService (?). Please make sure that the argument ModulesContainer at index [0] is available in the DiscoveryModule context.
Error log
Potential solutions:
If ModulesContainer is a provider, is it part of the current DiscoveryModule?
If ModulesContainer is exported from a separate #Module, is that module imported within DiscoveryModule? #Module({
imports: [ /* the Module containing ModulesContainer */ ] })
Error: Nest can't resolve dependencies of the DiscoveryService (?).
Please make sure that the argument ModulesContainer at index [0] is
available in the DiscoveryModule context.
library
import { DiscoveryService } from '#nestjs/core';
#Injectable()
export class EventPublishingService {
private readonly logger = new Logger(EventPublishingService.name);
private readonly publishingEventProviders;
constructor(
private discoveryService: DiscoveryService
) {
this.publishingEventProviders = this.discoveryService
.getProviders()
.filter(
({ metatype }) =>
metatype && Reflect.getMetadata(PUBLISHABLE_METADATA, metatype),
);
}
}
#Global()
#Module({
imports: [DiscoveryModule, HttpModule, ConfigModule],
providers: [
EventRegistrationService,
EventManagerServiceApi,
EventPublishingService],
exports: [EventPublishingService],
})
export class EventManagerModule {}
app module
#Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
cache: true,
load: [configuration],
}),
ScheduleModule.forRoot(),
MongooseModule.forRootAsync({
imports: [DataVaultManagerModule],
inject: [DataVaultManager],
useClass: MongooseConfigService,
}),
ParticipantsModule,
StudiesModule,
HealthModule,
EventManagerModule,
UsersModule,
],
controllers: [AppController],
providers: [
AppService,
{
provide: APP_PIPE,
useClass: ZodValidationPipe,
},
],
})
export class AppModule {}
Try changing constructor from EventPublishingService class like below:
constructor(
#Inject(DiscoveryService) private discoveryService: DiscoveryService
)

"Cannot find module" with NestJS

So, I have my RootModule, a ProductModule and a StoreModule.
My RootModule:
#Module({
imports: [
ProductModule,
StoreModule,
],
controllers: [],
providers: [],
})
export class RootModule {}
My ProductModule:
#Module({
providers: [ProductService],
exports: [],
})
export class ProductModule {}
My StoreModule:
#Module({
imports: []
providers: [StoreService, StoreWaitingService],
})
export class ProductModule {}
Since my RootModule imports ProductModule, shouldn't I be able to use ProductService on StoreService and StoreWaitingService?
What if I imported ProductModule on StoreModule imports?
You can use Product Module and Service in StoreService
Product Module
#Module({
providers: [ProductService],
exports: [ProductService],
})
export class ProductModule {}
Store Module
#Module({
imports: [ProductModule],
})
export class StoreModule{}
Store service
import ProductService from '<Product Service Path>';
...
constructor(private readonly productService: ProductService){}
...
//in Function
this.productService.someFunction();
But if you don't want to import the product module in Store Module, you can make the Product Module a global Module -
https://docs.nestjs.com/modules#global-modules

NestJs Authentication Circular Dependency

I am fairly new to nestJs. I am trying to implement an authentication process according to nestjs documentation, but I don't want to route the login in the app.controller I want to put it in the users.controller, so the route will be /users/login. However, since the AuthModule already uses the UsersService in my code and the login logic with JWT is in the AuthService. Importing it back to the UsersService create a circular dependency. I need help.
To avoid circular dependancy, in your UsersModule, you need to import your AuthModule with ForwardRef like that :
import ...
#Module( {
imports: [
forwardRef( () => AuthModule ),
],
controllers: [],
providers: [],
exports: []
} )
export class UsersModule {
}
If you haven't already done so, you'll need to export the AuthService in AuthModule :
import ...
#Module( {
imports: [],
controllers: [],
providers: [],
exports: [
AuthService
]
} )
export class AuthModule {
}

Nest can't resolve dependencies of the HttpService (?). Please make sure that the argument AXIOS_INSTANCE_TOKEN at index [0]

I'm implementing an API on NestJS that will consume another API, I'm using #nestjs/axios.
I followed this tutorial: https://docs.nestjs.com/techniques/http-module
But when I start the project with yarn start:dev
It is throwing an exception as:
ERROR [ExceptionHandler] Nest can't resolve dependencies of the HttpService (?). Please make sure that the argument AXIOS_INSTANCE_TOKEN at index [0] is available in the AxelGlobeModule context.
Potential solutions:
- If AXIOS_INSTANCE_TOKEN is a provider, is it part of the current AxelGlobeModule?
- If AXIOS_INSTANCE_TOKEN is exported from a separate #Module, is that module imported within AxelGlobeModule?
#Module({
imports: [ /* the Module containing AXIOS_INSTANCE_TOKEN */ ]
})
My app.module.ts
#Module({
imports: [
FileModule,
ConfigurationModule,
AxelGlobeModule,
HttpModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
timeout: configService.get('HTTP_TIMEOUT') || 1000,
maxRedirects: configService.get('HTTP_MAX_REDIRECTS') || 5,
baseURL: `{url}`,
paramsSerializer: (params) => {
return qs.stringify(
params,
PARAMS_SERIALIZER_DEFAULT_OPTIONS as IStringifyOptions,
);
},
}),
inject: [ConfigService],
}),
],
controllers: [AppController],
providers: [AppService, HttpModule, HttpService],
exports: [HttpModule],
})
My axel-globe.module.ts
#Module({
controllers: [AxelGlobeController],
imports: [ConfigModule.forRoot(), HttpModule],
providers: [AxelGlobeService, HttpService],
})
My service.ts
constructor(private readonly httpService: HttpService) {}
Anyone can help me?
drop that HttpService of your providers list. You just need to import HttpModule in order to have HttpService provider available to use. Follow the docs https://docs.nestjs.com/techniques/http-module#getting-started

Resources