Whay can't I return an entity or an array of entities? -> (Nestjs Typeorm: cannot find module error) - node.js

I have a nestjs application, that I wrote in typescript and I use TypeOrm and MySQL Workbench database. I don't know what could go worng, as it can't find my entity. A got an error like:
Cannot find module 'C:/Users/HP/Documents/prĂ³ba/test-crawler/src/database/entities/news.entity'
Although I only get this error when I want to retun an entity or an array of entities like:
return this.newsRepository.find()
Without this line the entity can be imported into the modules, everything is fine. I guess I did something wrong in the TypeOrm config, but I have already tried many ways I can't make it work.
Here is my repository: https://github.com/g937/web-crawler/tree/create-crawling-module

Write a file in your news module as a repository like news.repository.ts
Add the code like below
import { EntityRepository, Repository } from "typeorm"
import { NewsEntity } from "../database/entities/news.entity";
#EntityRepository(NewsEntity)
export class NewsEntityRepository extends Repository<NewsEntity> {}
and in your controller replace
constructor(
#InjectRepository(NewsEntity)
private readonly newsRepository: Repository<NewsEntity>,
) {}
to
constructor(
private readonly newsRepository: NewsEntityRepository,
) {}
Also change in the news.module.ts from
#Module({
imports: [TypeOrmModule.forFeature([NewsEntityRepository])],
providers: [NewsService],
controllers: [NewsController],
})
to
#Module({
imports: [TypeOrmModule.forFeature([NewsEntity])],
providers: [NewsService],
controllers: [NewsController],
})
Hopefully it will work

Related

NestJS inject custom TypeOrm repository based on an Interface

I'm currently working through the database integration docs for NestJS using TypeOrm. In these docs there are examples that show how to inject a custom database repository using the app.module from NestJS. All of these examples inject classes using the actual type of the custom repository.
#Injectable()
export class AuthorService {
constructor(private authorRepository: AuthorRepository) {}
}
This code is injected via the app.modules by providing a import like such:
#Module({
imports: [TypeOrmModule.forFeature([AuthorRepository])],
controller: [AuthorController],
providers: [AuthorService],
})
export class AuthorModule {}
This works well if you are fine with programming against an implementation, but I prefer to use an interface in my classes. I've already found the solution to injecting classes via an interface with NestJS in a previous question, but when I try to inject my custom repository like that, it doesn't seem to instanciate correctly and becomes undefined.
(node:16658) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'save' of undefined
Because of this, I assume you can only inject customRepositories via the forFeature() call in the app.module, but that won't allow me to use interfaces for injection, as far as I know. Is there any other way I can inject a custom TypeOrm repository without having the replace all my interfaces for the implementation of my custom repository? Thanks in advance!
Edit
Here is my current code, I managed to get it to inject, but this still forces me to use the implementation instead of the interface each time I call the constructor. This is mainly an issue when testing due to mocking.
#CommandHandler(FooCommand)
export class FooHandler
implements ICommandHandler<FooCommand> {
private fooRepository: IFooRepository; // Using Interface as a private property.
private barEventBus: IEventBus;
constructor(fooRepository: FooRepository,
barEventBus: EventBus) { // Forced to use implementation in constructor for injection.
this.fooRepository = fooRepository;
this.barEventBus = barEventBus;
}
#EntityRepository(FooEntity)
export class FooRepository extends Repository<FooEntity> implements IFooRepository {
getFoo() {
// Do stuff
}
}
#Module({
imports: [TypeOrmModule.forRoot(), TypeOrmModule.forFeature([FooRepository]],
// Other module setup
})
export class AppModule {}
It should work with using the InjectRepository decorator where you specify the Repository but then you type is as your interface instead and when testing you just provide the IFooRepository!
Example code:
constructor(#InjectRepository(FooRepository) fooRepository: IFooRepository,
barEventBus: EventBus) {
Edit: This answer is crap, that abstract-class-as-interface hack used does not work out as the defined methods seem to be optional to implement despite being marked as abstract.
Well, kind of got it working. Based on this answer https://stackoverflow.com/a/74561702/913136 I used an abstract class as interface (you can actually implement it) for not being required to pass strings around as tokens. Only drawback is the misuse of the abstract class. Not sure yet if I like it.
Using an actual interface in the same way seems not to be possible unfortunately. Urgh.
#Module({
imports: [
TypeOrmModule.forRoot({
...dataSource.options,
autoLoadEntities: true,
}),
TypeOrmModule.forFeature([Listing]),
],
controllers: [ViewListingController],
providers: [
{
provide: ListingRepository,
useClass: TypeOrmListingRepository,
},
],
})
makeshift interface:
import { Listing } from "./Listing";
export abstract class ListingRepository {
abstract findMostRecent: () => Promise<Listing[]>;
}
implementation:
import { Listing, ListingRepository } from "../../Domain";
import { Injectable } from "#nestjs/common";
import { Repository, DataSource } from "typeorm";
#Injectable()
export class TypeOrmListingRepository
extends Repository<Listing>
implements ListingRepository
{
constructor(private dataSource: DataSource) {
super(Listing, dataSource.createEntityManager());
}
findMostRecent() {
return this.find({});
}
}
import { Controller, Get } from "#nestjs/common";
import { ListingRepository } from "../Domain";
#Controller("listings")
export class ViewListingController {
constructor(private readonly listingRepo: ListingRepository) {}
#Get("/most-recent")
listMostRecent() {
return this.listingRepo.findMostRecent();
}
}

NestJS. Can't inject a repository from a different module

I am trying to use a typeorm custom repository defined in another module.
Following the documentation:
If you want to use the repository outside of the module which imports TypeOrmModule.forFeature, you'll need to re-export the providers generated by it. You can do this by exporting the whole module, like this:
#Module({
imports: [TypeOrmModule.forFeature([Role])],
exports: [TypeOrmModule]
})
export class RoleModule {}
Now if we import UsersModule in UserHttpModule, we can use #InjectRepository(User) in the providers of the latter module.
In my case i do:
#Module({
imports: [RoleModule],
providers: [UsersService],
controllers: [UsersController]
})
export class UserModule {}
Now when i inject the Role repository
export class UserService {
constructor(#InjectRepository(Role) private roleRepository: Repository<Role>) {}
}
i've got an error:
Nest can't resolve dependencies of the UserService (?).
Is it me or is the documentation incorrect?
Can someone suggest what is the error here or give a corrected example?
Try to add TypeOrmModule.forFeature([Role]) to imports:
#Module({
imports: [TypeOrmModule.forFeature([Role]), RoleModule], // <-- here
providers: [UsersService],
controllers: [UsersController]
})
export class UserModule {}

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 cannot resolve dependency index[0] when decorator is being used

I am new to NestJs and i have a question for you that i could not resolve it.
UsersService has two dependencies
-TypeOrm UsersRepository Injection
-WalletsService Injection
Typeorm injection is done by decorator as you see down below.
//UsersService
#Injectable()
export class UsersService implements IUserService {
constructor(
#InjectRepository(Users)
private usersRepository: Repository<Users>,
private readonly walletsService: WalletsService,
) { }
Whenever i changed first injection it cannot be resolved.
Probably i am missing something. There are all photos down below with description
//UsersModule
#Module({
controllers: [UsersController],
exports: [UsersService],
imports: [WalletsModule, TypeOrmModule.forFeature([Users])],
providers: [UsersService],
})
export class UsersModule { }
//WalletsModule
#Module({
controllers: [WalletsController],
exports: [WalletsService],
imports: [TypeOrmModule.forFeature([Wallets])],
providers: [WalletsService]
})
export class WalletsModule { }
[When Users Repository is first injection]
Nest can't resolve dependencies of the UsersService (?, WalletsService). Please make sure that the argument UsersRepository at index [0] is available in the UsersService context.
Potential solutions:
- If UsersRepository is a provider, is it part of the current UsersService?
- If UsersRepository is exported from a separate #Module, is that module imported within UsersService?
#Module({
imports: [ /* the Module containing UsersRepository */ ]
})
[When Wallets Service is first injection ]
Nest can't resolve dependencies of the UsersService (?, UsersRepository). Please make sure that the argument WalletsService at index [0] is available in the UsersService context.
Potential solutions:
- If WalletsService is a provider, is it part of the current UsersService?
- If WalletsService is exported from a separate #Module, is that module imported within UsersService?
#Module({
imports: [ /* the Module containing WalletsService */ ]
})
Thank you in advance. I hope it is descriptive enough. Have good day!
For posterity of the answer from the comments:
There was a service in an imports array which leads to problems with Nest trying to resolve things. In general, these errors can start to be debugged knowing that Nest's error is in the form of
Nest can't resolve dependencies of the UsersService (<dependencies_with_unknown_as_?>. Please make sure that the argument <unknown_dependency> at index [] is available in the <related_module> context.

NestJS cannot verify argument is available in current context/Mongoose Inject Model

I followed the MongoDB tutorial on the nestjs website but am unable to replicate it in my own project, I have cloned the nextjs repo and verified that the mongo sample supplied there runs fine.
This is what I currently have (minified):
app.module.ts
#Module({
imports: [
MongooseModule.forRoot('mongodb://localhost/nest')
],
modules: [
CampaignModule
]
})
export class AppModule implements NestModule {}
}
campaign.module.ts
#Module(
{
modules: [SharedModule],
controllers: [CampaignController],
components: [CampaignService],
imports: [MongooseModule.forFeature([{name: 'Campaign', schema: campaignSchema}])]
})
export class CampaignModule {}
campaign.service.ts
#Component()
export class CampaignService {
constructor(#InjectModel(campaignSchema) private readonly campaignModel: Model<CampaignInterface>) {}
}
this builds fine as expected but when I run it i get this error:
Nest can't resolve dependencies of the CampaignService (?). Please verify whether [0] argument is available in the current context.
So because in my app.module.ts I have the campaign module in the modules section (how i have had it so far working fine prior to mongodb) I moved it into the imports sections with the MongooseModule now it will build and run fine, but the routes inside the controller for campaign.controller.ts do not register at all, they just return 404's. This is weird because the example in the nestjs repo have the CatsModule inside the imports with the MongooseModule and it works.
Any tips here would be appreciated. this is my schema and interface for the campaign object as well:
export interface CampaignInterface extends Document, Campaign {
}
export const campaignSchema: any = new mongoose.Schema({
campaignId: String
});
EDIT 1
I moved all my modules into the import section of my app.module.ts file as before I tried it with CampaignModule in imports and all the others in modules: []. It now fails right away when served with the same error and no routes are registered.
Ok I figured out what is going on,
It seems that if you have both a modules: [] and imports: [] inside your #Module decorator the modules: [] takes over and completely ignores the imports: []. So in my campaign.module.ts file I moved the SharedModule from modules: [] into imports: [] after the MongooseModules.forFeature import. It now works and write to mongo!

Resources