0

The past few days I've been studying NestJS + Graphql + Mongoose building a small project but started to find some issues due to database relationship and circular dependency. At the moment I'm able to query a patient with a list of previous hospitalizations (code first)

type Patient {
  _id: ID!
  name: String!
  hospitalizations: [Hospitalization!]!
}

type Hospitalization {
  _id: ID!
  hospitalBed: Bed!
  patient: Patient!
}

type PaginatedHospitalization {
  totalCount: Int!
  edges: [HospitalizationEdge!]
  pageInfo: PageInfo!
}

type HospitalizationEdge {
  cursor: String!
  node: Hospitalization!
}

but I'm unable to update to update hospitalizations to be PaginatedHospitalization probably because of some circular dependency issue I'm unaware of. The error I'm getting on terminal when try to run the project is:

[8:35:19 AM] Starting compilation in watch mode...

[8:35:21 AM] Found 0 errors. Watching for file changes.

================ Hospitalization undefined
==== classRef undefined

/home/notroot/Documents/pessoal/_estudo/nest-graphql/src/common/entities/paginated.entity.ts:18
  @ObjectType(`${classRef.name}Edge`)
                          ^
TypeError: Cannot read properties of undefined (reading 'name')
    at Paginated (/home/notroot/Documents/pessoal/_estudo/nest-graphql/src/common/entities/paginated.entity.ts:18:27)
    at Object.<anonymous> (/home/notroot/Documents/pessoal/_estudo/nest-graphql/src/hospitalization/entities/paginated-hospitalization.entity.ts:9:56)
    at Module._compile (node:internal/modules/cjs/loader:1103:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/home/notroot/Documents/pessoal/_estudo/nest-graphql/src/patient/entities/patient.entity.ts:7:1)
    at Module._compile (node:internal/modules/cjs/loader:1103:14)

These are my modules

@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost:27017/nest-mongo'),
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
    }),
    BedModule,
    HospitalizationModule,
    PatientModule,
  ],
})
export class AppModule {}

@Module({
  imports: [
    MongooseModule.forFeature([{ name: Patient.name, schema: PatientSchema }]),
    forwardRef(() => HospitalizationModule),
  ],
  providers: [PatientResolver, PatientService],
  exports: [PatientService],
})
export class PatientModule {}

@Module({
  imports: [
    MongooseModule.forFeature([{ name: Bed.name, schema: BedSchema }]),
    forwardRef(() => HospitalizationModule),
  ],
  providers: [BedResolver, BedService],
  exports: [BedService],
})
export class BedModule {}

@Module({
  imports: [
    MongooseModule.forFeature([
      { name: Hospitalization.name, schema: HospitalizationSchema },
    ]),
    forwardRef(() => BedModule),
    forwardRef(() => PatientModule),
  ],
  providers: [HospitalizationResolver, HospitalizationService],
  exports: [HospitalizationService],
})
export class HospitalizationModule {}

These are my Entities

@Schema()
@ObjectType()
export class Patient extends BaseEntity {
  @Prop({ required: true })
  @Field()
  name: string;

  @Prop({
    type: [{ type: MongoSchema.Types.ObjectId, ref: 'Hospitalization' }],
  })
  // @Field(() => [Hospitalization], { defaultValue: [] })
  @Field(() => PaginatedHospitalization)
  hospitalizations?: Hospitalization[];
}

@Schema()
@ObjectType()
export class Bed extends BaseEntity {
  @Prop({ required: true })
  @Field()
  name: string;

  @Prop({
    type: [{ type: MongoSchema.Types.ObjectId, ref: 'Hospitalization' }],
  })
  @Field(() => [Hospitalization], { defaultValue: [] })
  // TODO: will be update to PaginatedHospitalization as well
  hospitalizations?: Hospitalization[];
}

@Schema()
@ObjectType()
export class Hospitalization extends BaseEntity {
  @Prop({ type: MongoSchema.Types.ObjectId, ref: 'Bed' })
  @Field(() => Bed)
  hospitalBed?: Bed;

  @Prop({ type: MongoSchema.Types.ObjectId, ref: 'Patient' })
  @Field(() => Patient)
  patient?: Patient;
}

My paginated object is based on this generic pagination object from NestJS documentation

export function Paginated<T>(classRef: Type<T>): Type<IPaginatedType<T>> {
  console.log('==== classRef', classRef);
  @ObjectType(`${classRef.name}Edge`)
  abstract class EdgeType {
    @Field(() => String)
    cursor: string;

    @Field(() => classRef)
    node: T;
  }

  @ObjectType({ isAbstract: true })
  abstract class PaginatedType implements IPaginatedType<T> {
    @Field(() => Int)
    totalCount: number;

    @Field(() => [EdgeType], { nullable: true })
    edges: EdgeType[];

    @Field(() => PageInfo)
    pageInfo: PageInfo;
  }

  return PaginatedType as Type<IPaginatedType<T>>;
}

console.log('================ Hospitalization', Hospitalization);

@ObjectType()
export class PaginatedHospitalization extends Paginated(Hospitalization) {}

On the docs and examples I saw multiple cases of separate modules like PetModule, OwnerModule but the docs says that circular dependency should be avoided where possible. Is this a case that I should have a single module that have Patient, Bed and Hospitalization on the same module or some other solution?

Gabriel Brito
  • 1,003
  • 2
  • 16
  • 26

0 Answers0