Find front end domain outside a NestJS Controller - nestjs

Similar to this, I am attempting to get the #Headers('origin') property inside a service which does not have its own controller and called to build email links for various other modules. Since the links are shared by email the front end domain triggering the call has to be identified which is done as follows :
import { Headers, Injectable } from '#nestjs/common';
// ... Other code specific imports
#Injectable()
export class LinkService {
constructor(#Headers('origin') private readonly origin: string) {}
createLink1(LinkId1: string): string {
return `${this.origin}/linkpath1/${LinkId1}`;
}
createLink2(LinkId2: string): string {
return `${this.origin}/linkpath2/${LinkId2}`;
}
// ... Similar follows
}
npm start leads to :
[Nest] 25971 - [ExceptionHandler] Nest can't resolve dependencies of the LinkService (?). Please make sure that the argument String at index [0] is available in the LinkModule context.
Potential solutions:
- If String is a provider, is it part of the current LinkModule?
- If String is exported from a separate #Module, is that module imported within LinkModule?
#Module({
imports: [ /* the Module containing String */ ]
})
+0ms
Error: Nest can't resolve dependencies of the LinkService (?). Please make sure that the argument String at index [0] is available in the LinkModule context.
Potential solutions:
- If String is a provider, is it part of the current LinkModule?
- If String is exported from a separate #Module, is that module imported within LinkModule?
#Module({
imports: [ /* the Module containing String */ ]
})
at Injector.lookupComponentInParentModules (/home/batfan47/graviti/check/graviti-api/node_modules/#nestjs/core/injector/injector.js:188:19)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async Injector.resolveComponentInstance (/home/batfan47/graviti/check/graviti-api/node_modules/#nestjs/core/injector/injector.js:144:33)
at async resolveParam (/home/batfan47/graviti/check/graviti-api/node_modules/#nestjs/core/injector/injector.js:98:38)
Would be great to know what would be the best way to go about this, so that the front end domain is available to me as required even in other parts of the code.

that #Headers('origin') on constructor just doens't make any sense. It must be in some method of your controller.
If you want the request object in some service, you could leverage on request scoped provider. Then you can retrieve the headers from it.

Related

Getting the metadata of the Module in NestJs

So, I came across a situation where I need to get the metadata of the Current Module, and its controllers.
ClosedModule.ts
// all imports to AModule, BModule
#Module({
imports: [
DiscoveryModule, // given by nest/core
AModule, // it has a controller AController whose base path is A/ and has 1 function for #Get a1
BModule, // it has a controller BController whose base path is B/ and has 1 function for #Get b1
],
})
export class ClosedModule implements OnModuleInit { // ---> (X)
constructor(private readonly discovery: DiscoveryService) {}
public async onModuleInit() {
const controllers = await this.discovery.getControllers({});
controllers.map(c => console.log('---->', c.name));
}
}
In above code:
DiscoveryService, DiscoveryModule imported from '#nestjs/core';
I tried getting the information using the above code. But, there are some issues:
I am getting all the controllers in the array, rather I just need
the controllers refs for the ClosedModule class i.e current class, (X).
How can I get the base path of all the controllers under a module which IMPORTED.
2.1 Other modules
2.2 Other Controllers
Thanks in advance
Happy Coding :)
You have access to a container in your module's constructor, which has all the configurations given to the imported modules.
Here
#Module({})
export class YourModules {
constructor(readonly modulesContainer: ModulesContainer) {
const modules = [...modulesContainer.values()];
for (const nestModule of modules) {
const modulePath: string = Reflect.getMetadata(MODULE_PATH, nestModule.metatype);
}
}
// ...
}
You can find a more detailed example in the nestjsx/nest-router library.

Nest can't resolve dependencies of AuthService

I am following the documentation present here
https://docs.nestjs.com/techniques/authentication#jwt-functionality
To have faster support I have created a git repository with the problem
https://github.com/Sano123456/nestjs-jwt
node -v -> v10.15.2
npm -v -> 6.14.6
nest -v -> 7.4.1
First Problem:
in AuthModule if I do as described in documentation and just import UserModule, it return me error of circular dependency between UserModule and AuthModule
#Module({
imports:[
UsersModule,
PassportModule
],
providers: [AuthService],
controllers: [AuthController],
exports:[AuthService, LocalStrategy]
})
export class AuthModule {}
error:
[ExceptionHandler] Nest cannot create the AuthModule instance.
The module at index [0] of the AuthModule "imports" array is undefined.
Potential causes:
- A circular dependency between modules. Use forwardRef() to avoid it. Read more: https://docs.nestjs.com/fundamentals/circular-dependency
- The module at index [0] is of type "undefined". Check your import statements and the type of the module.
Scope [AppModule -> UsersModule] +6ms
Possibile solution in imports array of AuthModule instead of UserModule put forwardRef(() => UsersModule),
this actually remove the error but not sure if this is the right way
Second problem:
it says that can't find LocalStrategy class even if it's present and declared in AuthModule
[ExceptionHandler] Nest cannot export a provider/module that is not a part of the currently processed module (AuthModule). Please verify whether the exported LocalStrategy is available in this particular context.Is LocalStrategy part of the relevant providers/imports within AuthModule?
Possibile solution right now I don't have any solution, I just remove it to understand what is the problem
Third problem :
after removing LocalStrategy,
[ExceptionHandler] Nest can't resolve dependencies of the AuthService (?). Please make sure that the argument dependency at index [0] is available in the AuthModule context.
Potential solutions:
- If dependency is a provider, is it part of the current AuthModule?
- If dependency is exported from a separate #Module, is that module imported within AuthModule?
#Module({
imports: [ /* the Module containing dependency */ ]
})
+1ms
Error: Nest can't resolve dependencies of the AuthService (?). Please make sure that the argument dependency at index [0] is available in the AuthModule context.
anyone solved this issues?
You have a circular dependancy because your UsersModule and your AuthModule import each other. Therefore you have 2 options to repair this issue.
The first is to make a forward reference which will allow both modules to be built simultaneously and once built, pass in the reference required. This is done like so:
#Module({
imports: [
forwardRef(() => UsersModule),
],
...
})
export class AuthModule {}
// And the same for your UsersModule
#Module({
imports: [
forwardRef(() => AuthModule),
],
})
export class UsersModule {}
The second option is to remove the dependancies from one another. This is not always possible and guessing by the names of your modules I would argue this isn't possible. You don't want to have the auth module accessing the user module's database and services etc outside the users module. But I'll give you some advice on module inheritance.
Module in nestjs are built asynchronously. Meaning they have to be structured like a cascading tree with one module importing all the others. Something linear will look like this
AppModule <= CatModule <= PawsModule
Another example would be dual importing
<= CatModule
AppModule <= PawsModule
<= DogModule
In the above example, the paws module is created once and imported in both cat and dog module. Meaning paws module will be built first before cat and dog module.
So to explain your error you need to think from a linear code perspective and how the module import tree will share modules that import each other. Because they import each other, nest can't decide which to create first so will need a reference to pass back, hence the function. I've always imagined the container's forward ref function as saying "Hey, hold this for a sec" (it's a piece of paper that says "UsersModule") then turns around, does some wavey of the arms with his back turned, then turns around and replaces the piece of paper with the UsersModule!
Your second issue is you never created a provider for LocalStrategy. It doesn't exist in the AuthModule so cannot be imported into AuthService nor exported from AuthModule!
** SOLUTION of problem "can't resolve dependencies" **
For the first and second problem the final solution is to use #Inject(forwardRef(() => AuthService)) in UserService
here is example
#Injectable()
export class UserService {
constructor(
#InjectRepository(User) private readonly UserRepository: Repository<User>,
private readonly config: ConfigService,
#Inject(forwardRef(() => AuthService)) //<---
private readonly authService: AuthService,
) {
}
Same thing also in AuthService
#Injectable()
export class AuthService {
private client: any;
constructor(
#Inject(forwardRef(() => UserService))//<--- here
private readonly userService: UserService,
#InjectConfig() private readonly config,
) {
}
In AuthModule and UserModule you need to still use forwardRef
I never used this solution before and i never needed it, but this solved my issue
Regarding LocalStrategy, put it in providers array of the module
For me, it wasn't enough to just use the forwardRef on both services as in Sano's answer; I also had to forwardRef on both circular dependent modules too.
In both services:
https://docs.nestjs.com/fundamentals/circular-dependency#forward-reference
import { forwardRef, Inject } from '#nestjs/common';
...
#Inject(forwardRef(() => UserService))`
In both modules:
https://docs.nestjs.com/fundamentals/circular-dependency#module-forward-reference
import { forwardRef } from '#nestjs/common';
...
imports: [
forwardRef(() => UsersModule),
],

Nestjs can't resolve dependencies of XModel

I have been working on this app for like 3 months which is near completion. But since yesterday I have been unable to solve this problem. I want to use activityTypeService in activityLogService and I have been getting this wired error. I have already exported activityTypeservice in its module. see below
below is ActivityTypeModule, I export ActivityTypeService so it can available in ActivityLogService
#Module({
imports: [MongooseModule.forFeature([{ name: 'ActivityType', schema: ActivityTypeSchema },])],
providers: [ActivityTypeService,],
controllers: [ActivityTypeController],
exports: [ActivityTypeService,]
})
export class ActivityTypeModule { }
The code below is activityLog module and ActivityTypeModule is imported
#Module({
imports: [MongooseModule.forFeature([{ name: 'ActivityLog', schema: ActivityLogSchema }]), ActivityTypeModule],
providers: [ActivityLogService, ActivityTypeModule],
controllers: [ActivityLogController],
exports: [MongooseModule,]
})
export class ActivityLogModule { }
so I use it the activityLogService as shown below
#Injectable()
export class ActivityLogService {
constructor(#InjectModel('ActivityLog') private activitylogModel: Model<ActivityLog>,
private activityTypeService: ActivityTypeService
) { }
async activitylog(activityuser: string, activitytype: string, activitydetails: string, activitydate: Date) {
const activitiesLog = {
activityuser: activityuser,
activitytype: activitytype,
activitydetails: activitydetails,
activitydate: activitydate
}
const activity = new this.activitylogModel(activitiesLog);
console.log(activity);
await activity.save()
}
}
But I am still getting this wired error which I dont understand
Nest can't resolve dependencies of the ActivityTypeService (?). Please make sure that the argument ActivityTypeModel at index [0] is available in the ActivityTypeService context.
Potential solutions:
- If ActivityTypeModel is a provider, is it part of the current ActivityTypeService?
- If ActivityTypeModel is exported from a separate #Module, is that module imported within ActivityTypeService?
#Module({
imports: [ /* the Module containing ActivityTypeModel */ ]
})
From your error, somewhere you have ActivityTypeService in an imports array somewhere, which shouldn't be happening. Along with that, I can see you have ActivityTypeModule in a providers array, which is also not supported, though Typescript doesn't have a good way to show errors about that, so you aren't seeing any errors.
In general, as Nest error like that is in the form of
Nest can't resolve dependencies of the <Provider> (?). Please make sure that the argument <injected_valued> at index [<index>] is available in the <module> context.
<Provider> and <module> should never be the same value, and if they are, it's a good indication that you have a provider in an imports array.

Using imported interceptor on controller not working in nestjs

I like to organise my project along feature lines with different modules for cross cutting concerns eg: configuration, authentication, etc. However when importing an Interceptor into a feature module for use with a Controller Nest doesn't seem to reuse the existing instance.
controllers.module.ts
#Module({
imports: [
// ConfigService is exported from this module.
ConfigModule
],
providers: [
// For debugging purposes I used a factory so I could place a breakpoint and see
// when the Interceptor is being created.
{
provide: MyInterceptor,
useFactory: (config: ConfigService) => new MyInterceptor(config),
inject: [
ConfigService
]
}
],
exports: [
MyInterceptor
]
})
export class ControllersModule {
}
customer.module.ts
#Module({
imports: [
ControllersModule
],
controllers: [
CustomerController
],
providers: [
CustomerService
]
})
export class CustomerModule {
}
customer.controller.ts
#Controller("/customers")
#UseInterceptors(MyInterceptor)
export class CustomerController {
constructor(private readonly customerService: CustomerService) {
}
#Get()
customers() {
return this.customerService.findAll();
}
}
When the application starts up, I can see the MyInterceptor provider factory being called, with an instance of ConfigService. However then I see the following error on the console
error: [ExceptionHandler] Nest can't resolve dependencies of the MyInterceptor (?). Please make sure that the argument ConfigService at index [0] is available in the CustomerModule context.
Potential solutions:
- If ConfigService is a provider, is it part of the current CustomerModule?
- If ConfigService is exported from a separate #Module, is that module imported within CustomerModule?
#Module({
imports: [ /* the Module containing ConfigService */ ]
})
Now maybe there's something about how Nest instantiates/uses Interceptors that I'm not understanding but I thought that given that MyInteceptor had been created, and the ControllersModule imported by CustomerModule that the bean would have been available and applied to CustomerController.
Is there something I'm missing here?
Interceptors (along with other request lifecycle classes) are kinda like pseudoproviders in that that are #Injectable() but they aren't added to a providers array for binding. You can bind then via the providers array, (APP_INTERCEPTOR) but that will cause it to be bound globally.
Because interceptors can't be added to a providers array the way you are trying, you need to instead add the ConfigModule to whatever module uses the interceptor.
and as a side-note, you shouldn't use #Res with interceptors in nestjs
why
look, when you are using an interceptor, you are handling (with using .handle()) the stream of response (observable) not a whole package of it, but using express #Res actually is somehow getting around the whole flow of response streaming.
this is also explicitly mentioned in nestjs official documents:
We already know that handle() returns an Observable. The stream
contains the value returned from the route handler, and thus we can
easily mutate it using RxJS's map() operator.
WARNING
The response mapping feature doesn't work with the
library-specific response strategy (using the #Res() object directly
is forbidden).

#Inject services in other service - Nest can't resolve dependencies

I'm trying to #Inject two services into a NestJS service and am getting
Nest can't resolve dependencies of the MainServiceImpl (?,
Symbol(MainDao)). Please make sure that the argument at index [0] is
available in the MainModule context
Here is the service:
#Injectable()
export class MainServiceImpl implements MainService {
constructor(
#Inject(TYPES.PublishSubscriptionService) private publishSubscriptionService: PublishSubscriptionService,
#Inject(TYPES.MainDao) private mainDao: MainDao
) {}
Now if I switch the order, it's always the second injected service that gets the error.
TYPES is an object of Symbols
const TYPES = {
PublishSubscriptionService: Symbol('PublishSubscriptionService'),
MainDao: Symbol('MainDao'),
};
export default TYPES;
Here is the index.ts which is using barreling
// start:ng42.barrel
export * from './main.dao.mongo-impl';
export * from './main.dao';
export * from './main';
export * from './main.schema';
export * from './main.service.impl';
export * from './main.service';
// end:ng42.barrel
What am I missing?
Closed NestJS issue with no resolution
NestJS doc on #Global modules
I can't say for sure without seeing your MainServieImplModule or whatever the module that contains this service is called, but if I had to guess, you are not declaring your providers to Nest correctly for these two services. You'll need to create a custom provider like so
#Module({
provides: [
{
provide: TYPES.PublishSubscriptionService,
useClass: PublishSubscriptionService,
},
{
provide: TYPES.MainDao,
useClass: MainDao
},
MainServiceImpl
]
})
export class MainServiceImplModule {}
If however, those providers are part of a different module you will need to make sure that the providers are custom (as above), but are also exported so they can be imported and used in a different module. Without seeing more of your code, the question is not possible to answer, but I think this should give you the direction you need. If not, please edit your question and add more information.
I don't know what TYPES is, you can use #Inject(PublishSubscriptionService) or you can use simply:
constructor(
private publishSubscriptionService: PublishSubscriptionService,
private mainDao: MainDao
) {}

Resources