简体   繁体   中英

NestJS Nest can't resolve dependencies of the RolesService (+, +, ?)

Hi I'm programming using the NestJS framework (with MongoDB) and have build some modules now. When I try to import a model from another module it returns this error:

Nest can't resolve dependencies of the RolesService (+, +, ?).

Now, I've implemented the code like this:

app.module.ts

import { GroupsModule } from './groups/groups.module';
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { UsersModule } from 'users/users.module';
import { RolesModule } from 'roles/roles.module';

@Module({
  imports: [
          MongooseModule.forRoot('mongodb://localhost:27017/example'),
          UsersModule,
          GroupsModule,
          RolesModule,
        ],
  providers: [],
})
export class AppModule {}

users.module.ts

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';

import { UsersController } from './users.controller';

import { UsersService } from './users.service';
import { RolesService } from 'roles/roles.service';

import { UserSchema } from './schemas/user.schema';
import { RoleSchema } from 'roles/schemas/role.schema';

@Module({
    imports: [
      MongooseModule.forFeature([{ name: 'User', schema: UserSchema }]),
      MongooseModule.forFeature([{ name: 'Role', schema: RoleSchema }]),
    ],
    controllers: [UsersController],
    providers: [UsersService, RolesService],
    exports: [UsersService],
  })

export class UsersModule {}

users.service.ts

import { Model } from 'mongoose';
import { ObjectID } from 'mongodb';
import { InjectModel } from '@nestjs/mongoose';
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';

import { User } from './interfaces/user.interface';

@Injectable()
export class UsersService {
  constructor(@InjectModel('User') private readonly userModel: Model<User>) {}
}

groups.module.ts

import { MongooseModule } from '@nestjs/mongoose';

import { GroupsController } from './groups.controller';

import { RolesService } from '../roles/roles.service';
import { GroupsService } from './groups.service';

import { GroupSchema } from './schemas/group.schema';
import { UserSchema } from '../users/schemas/user.schema';
import { RoleSchema } from '../roles/schemas/role.schema';

@Module({
  imports: [
    MongooseModule.forFeature([{ name: 'Group', schema: GroupSchema }]),
    MongooseModule.forFeature([{ name: 'User', schema: UserSchema }]),
    MongooseModule.forFeature([{ name: 'Role', schema: RoleSchema }]),
  ],
  controllers: [GroupsController],
  providers: [GroupsService, RolesService],
  exports: [GroupsService],
})

groups.service.ts

import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { ObjectID } from 'mongodb';
import { Model } from 'mongoose';

import { Group } from './interfaces/group.interface';
import { User } from '../users/interfaces/user.interface';

import { CreateGroupDto } from './dto/create-group.dto';
import { RolesDto } from 'roles/dto/roles.dto';
import { Role } from '../roles/interfaces/role.interface';

@Injectable()
export class GroupsService {
    constructor(@InjectModel('Group') private readonly groupModel: Model<Group>,
                @InjectModel('Role') private readonly roleModel: Model<Role>) {} }

roles.module.ts

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';

import { RolesController } from './roles.controller';

import { RolesService } from './roles.service';

import { RoleSchema } from './schemas/role.schema';
import { UserSchema } from '../users/schemas/user.schema';
import { GroupSchema } from '../groups/schemas/group.schema';

@Module({
    imports: [
      MongooseModule.forFeature([{ name: 'User', schema: UserSchema }]),
      MongooseModule.forFeature([{ name: 'Role', schema: RoleSchema }]),
      MongooseModule.forFeature([{ name: 'Group', schema: GroupSchema }]),
    ],
    controllers: [RolesController],
    providers: [RolesService],
    exports: [RolesService],
  })

export class RolesModule {}

roles.service.ts

import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { ObjectID } from 'mongodb';
import { Model } from 'mongoose';

import { Role } from './interfaces/role.interface';
import { User } from '../users/interfaces/user.interface';
import { Group } from '../groups/interfaces/group.interface';

import { CreateRoleDto } from './dto/create-role.dto';
import { RolesDto } from './dto/roles.dto';

@Injectable()
export class RolesService {
    constructor( @InjectModel('Role') private readonly roleModel: Model<Role>,
                 @InjectModel('User') private readonly userModel: Model<User>,
                 @InjectModel('Group') private readonly groupModel: Model<Group> ) {} }

While the DI in the users and roles works fine, the error arise when I try to import the Group Model in the roles service. Please tell me if you see anything wrong, I've follow the same schema from users with groups but unfortunately can't see where the error lives.

Thanks in advance.

UPDATE: OK I think my error is when I try to use a module service function outside the module. I mean I modified (in order to simplify) I'll modify the code this way:

users.module.ts

@Module({
    imports: [
      MongooseModule.forFeature([{ name: 'User', schema: UserSchema }]),
      RolesModule,
    ],
    controllers: [UsersController],
    providers: [UsersService, RolesService],
    exports: [UsersService],
  })

export class UsersModule {}

users.controller.ts

export class UsersController {

    constructor(private readonly usersService: UsersService,
                private readonly rolesService: RolesService){}

    async addRoles(@Param('id') id: string, @Body() userRolesDto: UserRolesDto): Promise<User> {
        try {
            return this.rolesService.setRoles(id, userRolesDto);
        } catch (e){
            const message = e.message.message;
            if ( e.message.error === 'NOT_FOUND'){
                throw new NotFoundException(message);
            } else if ( e.message.error === 'ID_NOT_VALID'){
                throw new BadRequestException(message);
            }
        }

    }

}

roles.module.ts

@Module({
    imports: [
      MongooseModule.forFeature([{ name: 'Role', schema: RoleSchema }]),
    ],
    controllers: [RolesController],
    providers: [RolesService],
    exports: [RolesService],
  })

export class RolesModule {}

roles.service.ts

@Injectable()
export class RolesService {
    userModel: any;
    constructor( @InjectModel('Role') private readonly roleModel: Model<Role> ) {}

    // SET USER ROLES
    async setRoles(id: string, rolesDto: RolesDto): Promise<User> {
        if ( !ObjectID.isValid(id) ){
            throw new HttpException({error: 'ID_NOT_VALID', message: `ID ${id} is not valid`, status: HttpStatus.BAD_REQUEST}, 400);
        }
        try {
            const date = moment().valueOf();
            const resp = await this.userModel.updateOne({
              _id: id,
            }, {
              $set: {
                  updated_at: date,
                  roles: rolesDto.roles,
              },
            });
            if ( resp.nModified === 0 ){
              throw new HttpException({ error: 'NOT_FOUND', message: `ID ${id} not found or entity not modified`, status: HttpStatus.NOT_FOUND}, 404);
            } else {
              let user = await this.userModel.findOne({ _id: id });
              user = _.pick(user, ['_id', 'email', 'roles', 'created_at', 'updated_at']);
              return user;
            }
        } catch (e) {
          if ( e.message.error === 'NOT_FOUND' ){
            throw new HttpException({ error: 'NOT_FOUND', message: `ID ${id} not found or entity not modified`, status: HttpStatus.NOT_FOUND}, 404);
          } else {
            throw new HttpException({error: 'ID_NOT_VALID', message: `ID ${id} is not valid`, status: HttpStatus.BAD_REQUEST}, 400);
          }
        }
    }

That's it, as you can see when I try to use from users.controller the roles.service setRole method it returns me an error:

Nest can't resolve dependencies of the RolesService (?). Please make sure that the argument at index [0]is available in the current context.

I don't understand where the problem is because I'm injecting the Role model in the roles.module already and it don't understand it. In fact if I don't create the call from users.module to this dependency everything goes fine.

Any tip?

(I've red the suggestion from stackoverflow, I'll don't do it again)

I think the problem is that you're importing the same model multiple times, like:

MongooseModule.forFeature([{ name: 'User', schema: UserSchema }]

and also providing the same service multiple times:

providers: [RolesService]

I would not inject the models themselves but rather the corresponding services that encapsulate the model. Then you export the service in its module and import the module where needed. So the RolesService would inject the UsersSerivce instead of the UserModel .

With your current setup, you would run into circular dependencies though. This can be handled with fowardRef(() => UserService) but should be avoided if possible, see the circular dependency docs . If this is avoidable depends on your business logic however.

If you don't have circular dependencies then for example export your RolesService

@Module({
    imports: [MongooseModule.forFeature([{ name: 'Role', schema: RoleSchema }])]
    controllers: [RolesController],
    providers: [RolesService],
    exports: [RolesService],
  })

export class RolesModule {}

and import the RolesModule wherever you want to use the RolesService , eg:

@Module({
    imports: [
      RolesModule,
      MongooseModule.forFeature([{ name: 'User', schema: UserSchema }])
    ],
    controllers: [UsersController],
    providers: [UsersService],
    exports: [UsersService],
  })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM