NestJS 依赖注入 – 从解析器的构造函数中删除垃圾

huangapple go评论103阅读模式
英文:

NestJS dependency injection - delete garbage from constructor in resolver

问题

我已经看到你的代码并了解了你的问题。你的问题似乎与依赖注入有关,特别是在NestJS中如何正确注入依赖。

首先,你尝试使用UserRepoSymbol来提供UserPostgresql,然后在UserService中注入它,这是一个正确的做法。但是,根据你的错误消息,问题可能出在配置文件的导入和环境变量的设置上。

确保以下几点:

  1. 确保你的.env文件路径正确,并且文件包含所需的环境变量。你可以在 dotenv.config({ path: ENV_FILE_PATH }) 这一行之后添加 console.log(process.env) 来检查是否成功加载了环境变量。

  2. 确保 UserRepoSymbol 的值与你的提供者名称一致。在你的模块中,你提供了一个名称为Object的提供者,但在注入时使用的是 UserRepoSymbol。确保它们匹配。

  3. 检查 UserPostgresql 是否正确导入并在 providers 数组中添加到 UserModule 中。

如果你仍然遇到问题,可以提供更多关于错误消息的信息,以便我能够提供更具体的帮助。

英文:

So I have been working on a NestJs+Graphql+Postgresql application using ddd architecture. And now it just adds user to a database.

I have the following user.resolver in the presentation layer:

  1. @Resolver(of => UserBaseWithPassword)
  2. export class UserResolver {
  3. private readonly userApplication: UserApplication
  4. constructor(private readonly userRepo: UserPostgresql) {
  5. const userService = new UserService(userRepo)
  6. this.userApplication = new UserApplication(userService)
  7. }
  8. @Query(returns => String)
  9. users() : string {
  10. return "";
  11. }
  12. @Mutation(returns => String)
  13. async createUser(@Args('createUserDTO') createUserWithPasswordDTO: CreateUserWithPasswordDTO): Promise<string> {
  14. return await this.userApplication.create(createUserWithPasswordDTO=createUserWithPasswordDTO)
  15. }
  16. }

It works fine, but I need to get rid of garbage in the constructor.
Here is my application layer's
user.ts :

  1. export class UserApplication{
  2. constructor(private userService: UserService) {}
  3. async create(createUserWithPasswordDTO: CreateUserWithPasswordDTO): Promise<string> {
  4. return await this.userService.create(createUserWithPasswordDTO=createUserWithPasswordDTO);
  5. }
  6. }

In the domain layer i have user.service.ts :

  1. @Injectable()
  2. export class UserService {
  3. constructor(private readonly userRepo: IUserRepo) {}
  4. async create(createUserWithPasswordDTO: CreateUserWithPasswordDTO): Promise<string> {
  5. this.validateEmail(createUserWithPasswordDTO.email)
  6. this.validatePassword(createUserWithPasswordDTO.password)
  7. try{
  8. createUserWithPasswordDTO.password = await this.hashPassword(createUserWithPasswordDTO.password);
  9. return await this.userRepo.create(createUserWithPasswordDTO);
  10. }catch(e){
  11. throw new Error("DEFAULT_USER_ERROR"+e)
  12. }
  13. }
  14. private async hashPassword(password: string): Promise<string> {
  15. const saltRounds = process.env.PASSWORD_SALT_ROUNDS;
  16. return await bcrypt.hash(password, saltRounds);;
  17. }
  18. private validateEmail(email: string): boolean {
  19. if(email.length < MIN_EMAIL_LENGTH)
  20. throw new Error(EMAIL_MIN_LENGTH_TEXT)
  21. if(email.length > MAX_EMAIL_LENGTH)
  22. throw new Error(EMAIL_MAX_LENGTH_TEXT)
  23. if(!EMAIL_REGEX.test(email))
  24. throw new Error(EMAIL_REGEX_TEXT)
  25. return true;
  26. }
  27. private validatePassword(password: string): boolean {
  28. if(password.length < MIN_PASSWORD_LENGTH || password.length > MAX_PASSWORD_LENGTH)
  29. throw new Error(PASSWORD_LENGTH_ERROR_TEXT)
  30. if(!PASSWORD_HAS_NUMBER_REGEX.test(password))
  31. throw new Error(PASSWORD_NOT_INCLUDES_NUMBER_TEXT)
  32. if(!PASSWORD_HAS_LETTER_REGEX.test(password))
  33. throw new Error(PASSWORD_NOT_INCLUDES_LETTER_TEXT)
  34. return true;
  35. }
  36. }

and an Interface user.repo :

  1. import { CreateUserWithPasswordDTO } from "./dtos/create-user.dto";
  2. export interface IUserRepo {
  3. create(createUserWithPasswordDTO: CreateUserWithPasswordDTO): Promise<string>
  4. }

And lastly, in the infrustructure layer I have repo.ts, that implements interface UserRepo :

  1. @Injectable()
  2. export class UserPostgresql implements IUserRepo{
  3. constructor(@InjectDataSource() private dataSource: DataSource) {}
  4. async create(createUserWithPasswordDTO: CreateUserWithPasswordDTO): Promise<string> {
  5. const parameters = [uuidv4(), createUserWithPasswordDTO.email, createUserWithPasswordDTO.password]
  6. const reply = await this.dataSource.query(CREATE_USER, parameters)
  7. return reply[0].id
  8. }
  9. }

I mention all above in the user.module :

  1. import * as dotenv from 'dotenv';
  2. const ENV_FILE_PATH = './ci/postgres/.env'
  3. dotenv.config({path: ENV_FILE_PATH});
  4. @Module({
  5. imports: [TypeOrmModule.forFeature([User])],
  6. controllers: [],
  7. providers: [
  8. Object,
  9. UserPostgresql,
  10. UserService,
  11. UserApplication,
  12. UserPostgresql,
  13. UserResolver
  14. ]
  15. })
  16. export class UserModule {}

I write Object in the @Module, because program doesn't compile without it which is also an issue.

I tried to write in user.module something like

  1. {
  2. provide: UserRepoSymbol,
  3. useClass: UserPostgresql,
  4. },

then changing constructor in the user.service to :

  1. constructor(@Inject(UserRepoSymbol) private readonly userRepo: IUserRepo) {}

and also changing the user.resolver's constructor just to:


constructor(private readonly userApplication: UserApplication) {}

but it seems not to work and i get an error :

  1. TypeError: Cannot read properties of undefined (reading 'create')
  2. at UserApplication.create (C:\path\api-service\src\application\user.ts:8:39)
  3. at UserResolver.createUser (C:\path\src\presentation\user\user.resolver.ts:20:43)...

答案1

得分: 0

我忘记了在 user.application 中使用 @Injectable 装饰器。

英文:

I forgot @Injectable decorator in user.application

huangapple
  • 本文由 发表于 2023年6月25日 22:07:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76550803.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定