Michael Jiang
Michael Jiang

Reputation: 3

Sharing services across nestjs modules

I'm working on a personal project where I follow a repository pattern and inject the repositories to my services(I don't use typeorm, i use prisma). Now i'm running into a problem where in the auth module i want to access data by using the usersService, which is exported in my usersModule, and my auth module also imports the usersModule, but it's always giving the error that nest can't resolve dependency of usersService in authService. Can y'all give me a hand on this problem?

users.service.ts:

import { Inject, Injectable } from "@nestjs/common";
import { CreateUserDto } from "./dto/create-user.dto";
import { IUserRepository } from "./user.types";
import { TYPES } from "../app.types";
import { UserOutput } from "./dto/user.output";

@Injectable()
export class UsersService {
  constructor(
    @Inject(TYPES.User) private readonly userRepository: IUserRepository
  ) {}

  async create(data: CreateUserDto): Promise<UserOutput | null> {
    return await this.userRepository.createUser(data);
  }
}

users.repository.ts:

import { HttpStatus, Injectable } from "@nestjs/common";
import { PrismaService } from "../prisma/prisma.service";
import { CreateUserDto } from "./dto/create-user.dto";
import { UserOutput } from "./dto/user.output";
import { IUserRepository } from "./user.types";
import { ConfigService } from "@nestjs/config";
import { IEnv } from "../env.types";
import { HttpException } from "@nestjs/common";

@Injectable()
export class UserRepository implements IUserRepository {
  constructor(
    private readonly prismaService: PrismaService,
    private readonly configService: ConfigService<IEnv>
  ) {}

  async createUser(data: CreateUserDto): Promise<UserOutput> {
    let { userName, password } = data;
    try {
      const user = await this.prismaService.user.findFirst({
        where: { userName: userName },
      });
      if (user) {
        throw new HttpException(
          "User Already Exists",
          HttpStatus.UNPROCESSABLE_ENTITY
        );
      }
      const userCreated = await this.prismaService.user.create({
        data: { userName: userName, password: hashedPassword as any },
      });
    } catch (e) {
      console.log(e);
      throw e;
    }


}

users.module.ts

import { Module } from "@nestjs/common";
import { UsersService } from "./users.service";
import { UsersController } from "./users.controller";
import { TYPES } from "../app.types";
import { UserRepository } from "./users.repository";

@Module({
  controllers: [UsersController],
  providers: [
    UsersService,
    {
      provide: TYPES.User,
      useClass: UserRepository,
    },
  ],
  exports: [UsersService],
})
export class UsersModule {}

auth.module.ts:

import { Global, Module } from "@nestjs/common";
import { UsersModule } from "../users/users.module";
import { ValidateService } from "./validate.token.service";

@Global()
@Module({
  imports: [UsersModule],
  providers: [ValidateService],
  exports: [ValidateService],
})
export class AuthModule {}

auth.service.ts:

import { Injectable, UnauthorizedException } from "@nestjs/common";
import { Request } from "express";
import { ConfigService } from "@nestjs/config";
import { IEnv } from "../env.types";
import jwt from "jwt-simple";
import { UsersService } from "../users/users.service";

@Injectable()
export class AuthService {
  constructor(
    private readonly userService: UsersService,
    private readonly configService: ConfigService<IEnv>
  ) {}
  async verifyToken(request: Request): Promise<boolean> {
    const token = request.headers.authorization;
    if (!token) throw new UnauthorizedException();
    try {
      const secretKey = this.configService.get("SECRET_KEY");
      const payload = jwt.decode(token, secretKey);
      const user = await this.userService.findOne(payload.sub);
      if (user) {
        return true;
      }
      return false;
    } catch (e) {
      return false;
    }
  }
}

btw, TYPES.user = Symbol('User')

Upvotes: 0

Views: 1751

Answers (1)

Gpack
Gpack

Reputation: 2203

In this case, they usually recommend to use forwardRef to work around the circular dependency.

Upvotes: 0

Related Questions