0
votes

In my NestJs API, I was getting the following error because I was using the EmployerService in the CandidateService.

Error: Nest can't resolve dependencies of the CandidateService (CandidateRepository, AddressRepository, ProvinceRepository, ?). Please make sure that the argument EmployerService at index [3] is available in the CandidateModule context.

Potential solutions:
- If EmployerService is a provider, is it part of the current CandidateModule?
- If EmployerService is exported from a separate @Module, is that module imported within CandidateModule?
  @Module({
    imports: [ /* the Module containing EmployerService */ ]
  })

I solved this by adding the EmployerModule into the CandidateModule imports as shown below.

@Module({
  imports: [
    EmployerModule,
    TypeOrmModule.forFeature([Candidate, Address, Province]),
  ],
  providers: [CandidateResolver, CandidateService],
  exports: [CandidateService, TypeOrmModule],
})
export class CandidateModule {}

This seems to have fixed the previous error but also created the following error.

UnhandledPromiseRejectionWarning: Error: Cannot determine a GraphQL input type for the "employer". Make sure your class is decorated with an appropriate decorator.
at InputTypeFactory.create (/Users/amed/Documents/Projects/jnoble/packages/api/node_modules/@nestjs/graphql/dist/schema-builder/factories/input-type.factory.js:19:23)
at /Users/amed/Documents/Projects/jnoble/packages/api/node_modules/@nestjs/graphql/dist/schema-builder/factories/input-type-definition.factory.js:44:52
at Array.forEach (<anonymous>)
at /Users/amed/Documents/Projects/jnoble/packages/api/node_modules/@nestjs/graphql/dist/schema-builder/factories/input-type-definition.factory.js:42:33
at resolveThunk (/Users/amed/Documents/Projects/jnoble/packages/api/node_modules/graphql/type/definition.js:480:40)
at defineInputFieldMap (/Users/amed/Documents/Projects/jnoble/packages/api/node_modules/graphql/type/definition.js:1207:18)
at GraphQLInputObjectType.getFields (/Users/amed/Documents/Projects/jnoble/packages/api/node_modules/graphql/type/definition.js:1155:27)
at collectReferencedTypes (/Users/amed/Documents/Projects/jnoble/packages/api/node_modules/graphql/type/schema.js:376:81)
at collectReferencedTypes (/Users/amed/Documents/Projects/jnoble/packages/api/node_modules/graphql/type/schema.js:372:11)
at new GraphQLSchema (/Users/amed/Documents/Projects/jnoble/packages/api/node_modules/graphql/type/schema.js:157:7)

I cannot figure out why I am getting this error. You can see what my entity and @nestjs/graphql input looks like below.

employer.entity.ts

@ObjectType()
@Entity()
export class Employer {
  @PrimaryGeneratedColumn()
  @Field(() => Int)
  id: number;

  @Column()
  @Field()
  name: string;

  @Column({ unique: true })
  @Field()
  email: string;

  @Column()
  @Field()
  phone: string;

  @Column()
  @Field()
  industry: string;

  @OneToOne(() => Address, address => address.employer, {
    cascade: ['insert', 'update'],
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'address_id' })
  @Field(() => Address)
  address: Address;

  @OneToMany(() => Candidate, candidate => candidate.employer, {
    cascade: ['insert', 'update'],
    onDelete: 'CASCADE',
    nullable: true,
  })
  @JoinColumn({ name: 'employees_id' })
  @Field(() => [Candidate], { nullable: true })
  employees?: Candidate[];

  @OneToMany(() => SubUser, sub => sub.employer)
  @JoinColumn({ name: 'sub_id' })
  @Field(() => [SubUser])
  sub: SubUser[];

  @CreateDateColumn({ name: 'created_at' })
  @Field()
  createdAt: string;

  @UpdateDateColumn({ name: 'updated_at' })
  @Field()
  updatedAt: string;
}

employer.input.ts

@InputType()
export class EmployerInput {
  @Field()
  name: string;

  @Field()
  email: string;

  @Field()
  phone: string;

  @Field()
  industry: string;
}

employer.resolver.ts

@Resolver()
export class EmployerResolver {
  constructor(private readonly employerService: EmployerService) {}

  @Query(() => [Employer], { nullable: true })
  async allEmployers(): Promise<Employer[]> {
    return await this.employerService.findAll();
  }

  @Query(() => [Employer], { nullable: true })
  async employerByName(@Args('input') input: string): Promise<Employer[]> {
    return await this.employerService.findByName(input);
  }

  @Query(() => [Employer], { nullable: true })
  async employerByEmail(@Args('input') input: string): Promise<Employer> {
    return await this.employerService.findByEmail(input);
  }

  @Query(() => [Employer], { nullable: true })
  async employerById(
    @Args('id', { type: () => Int }) id: number,
  ): Promise<Employer> {
    return await this.employerService.findById(id);
  }

  @Mutation(() => Employer)
  async addEmployer(
    @Args('sub') sub: SubUserInput,
    @Args('employer')
    employer: EmployerInput,
    @Args('address') address: AddressInput,
    @Args('province') province: ProvinceInput,
  ): Promise<Employer> {
    return await this.employerService.addEmployer(
      sub,
      employer,
      address,
      province,
    );
  }

  @Mutation(() => Employer)
  async updateEmployer(
    @Args('id', { type: () => Int }) id: number,
    @Args('input')
    input: EmployerUpdateInput,
    @Args('province', { nullable: true }) province: ProvinceInput,
  ): Promise<Employer> {
    return await this.employerService.updateEmployer(id, input, province);
  }
}

Anyone with some insights on this, please help. Thank You.

1
Can you show the resovler that uses employer? From the error, it seems you're trying to make an input be of type Employer instead of EmployerInput. - Jay McDoniel
@JayMcDoniel I have added the employer resolver - Ahmed F.
I also have this in my Candidate Input @Field({ nullable: true }) employer?: Employer; - Ahmed F.
That's probably where the error is. I would bet that should be EmployerInput type - Jay McDoniel

1 Answers

1
votes

I found the error thanks to Jay in the comments.

candidate.input.ts

@InputType()
export class CandidateInput {
  @Field()
  firstName: string;

  @Field()
  lastName: string;

  @Field({ nullable: true })
  middleName: string;

  @Field({ nullable: true })
  preferredName: string;

  @Field()
  dateOfBirth: string;

  @Field()
  jobTitle: string;

  @Field()
  phone: string;

  @Field()
  email: string;

  @Field({ nullable: true })
  password?: string;

  @Field({ nullable: true }) 
  employer: Employer; // This is where the error originates

  @Field(() => [String])
  languages: string[];

  @Field(() => [String])
  skills: string[];

  @Field({ nullable: true })
  validDriversLicense: boolean;

  @Field({ nullable: true })
  ownVehicle: boolean;

  @Field()
  statusInCanada: string;

  @Field()
  available: boolean;
}

I changed the problematic field to

@Field(() => Int, { nullable: true })
employerId?: number;

And that fixed it.