英文:
NestJS dependency injection - delete garbage from constructor in resolver
问题
我已经看到你的代码并了解了你的问题。你的问题似乎与依赖注入有关,特别是在NestJS中如何正确注入依赖。
首先,你尝试使用UserRepoSymbol
来提供UserPostgresql
,然后在UserService
中注入它,这是一个正确的做法。但是,根据你的错误消息,问题可能出在配置文件的导入和环境变量的设置上。
确保以下几点:
-
确保你的
.env
文件路径正确,并且文件包含所需的环境变量。你可以在dotenv.config({ path: ENV_FILE_PATH })
这一行之后添加console.log(process.env)
来检查是否成功加载了环境变量。 -
确保
UserRepoSymbol
的值与你的提供者名称一致。在你的模块中,你提供了一个名称为Object
的提供者,但在注入时使用的是UserRepoSymbol
。确保它们匹配。 -
检查
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:
@Resolver(of => UserBaseWithPassword)
export class UserResolver {
private readonly userApplication: UserApplication
constructor(private readonly userRepo: UserPostgresql) {
const userService = new UserService(userRepo)
this.userApplication = new UserApplication(userService)
}
@Query(returns => String)
users() : string {
return "";
}
@Mutation(returns => String)
async createUser(@Args('createUserDTO') createUserWithPasswordDTO: CreateUserWithPasswordDTO): Promise<string> {
return await this.userApplication.create(createUserWithPasswordDTO=createUserWithPasswordDTO)
}
}
It works fine, but I need to get rid of garbage in the constructor.
Here is my application layer's
user.ts :
export class UserApplication{
constructor(private userService: UserService) {}
async create(createUserWithPasswordDTO: CreateUserWithPasswordDTO): Promise<string> {
return await this.userService.create(createUserWithPasswordDTO=createUserWithPasswordDTO);
}
}
In the domain layer i have user.service.ts :
@Injectable()
export class UserService {
constructor(private readonly userRepo: IUserRepo) {}
async create(createUserWithPasswordDTO: CreateUserWithPasswordDTO): Promise<string> {
this.validateEmail(createUserWithPasswordDTO.email)
this.validatePassword(createUserWithPasswordDTO.password)
try{
createUserWithPasswordDTO.password = await this.hashPassword(createUserWithPasswordDTO.password);
return await this.userRepo.create(createUserWithPasswordDTO);
}catch(e){
throw new Error("DEFAULT_USER_ERROR"+e)
}
}
private async hashPassword(password: string): Promise<string> {
const saltRounds = process.env.PASSWORD_SALT_ROUNDS;
return await bcrypt.hash(password, saltRounds);;
}
private validateEmail(email: string): boolean {
if(email.length < MIN_EMAIL_LENGTH)
throw new Error(EMAIL_MIN_LENGTH_TEXT)
if(email.length > MAX_EMAIL_LENGTH)
throw new Error(EMAIL_MAX_LENGTH_TEXT)
if(!EMAIL_REGEX.test(email))
throw new Error(EMAIL_REGEX_TEXT)
return true;
}
private validatePassword(password: string): boolean {
if(password.length < MIN_PASSWORD_LENGTH || password.length > MAX_PASSWORD_LENGTH)
throw new Error(PASSWORD_LENGTH_ERROR_TEXT)
if(!PASSWORD_HAS_NUMBER_REGEX.test(password))
throw new Error(PASSWORD_NOT_INCLUDES_NUMBER_TEXT)
if(!PASSWORD_HAS_LETTER_REGEX.test(password))
throw new Error(PASSWORD_NOT_INCLUDES_LETTER_TEXT)
return true;
}
}
and an Interface user.repo :
import { CreateUserWithPasswordDTO } from "./dtos/create-user.dto";
export interface IUserRepo {
create(createUserWithPasswordDTO: CreateUserWithPasswordDTO): Promise<string>
}
And lastly, in the infrustructure layer I have repo.ts, that implements interface UserRepo :
@Injectable()
export class UserPostgresql implements IUserRepo{
constructor(@InjectDataSource() private dataSource: DataSource) {}
async create(createUserWithPasswordDTO: CreateUserWithPasswordDTO): Promise<string> {
const parameters = [uuidv4(), createUserWithPasswordDTO.email, createUserWithPasswordDTO.password]
const reply = await this.dataSource.query(CREATE_USER, parameters)
return reply[0].id
}
}
I mention all above in the user.module :
import * as dotenv from 'dotenv';
const ENV_FILE_PATH = './ci/postgres/.env'
dotenv.config({path: ENV_FILE_PATH});
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [],
providers: [
Object,
UserPostgresql,
UserService,
UserApplication,
UserPostgresql,
UserResolver
]
})
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
{
provide: UserRepoSymbol,
useClass: UserPostgresql,
},
then changing constructor in the user.service to :
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 :
TypeError: Cannot read properties of undefined (reading 'create')
at UserApplication.create (C:\path\api-service\src\application\user.ts:8:39)
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论