-
Question: If I have two To explain with context... Model User: @ObjectType()
@modelOptions({
schemaOptions: {
timestamps: true
}
})
export class User {
@Field()
readonly _id!: string
@Field()
readonly token!: string
@Field()
@prop({ required: true })
username!: string
@Field()
@IsEmail()
@prop({ required: true })
email!: string
@Field()
@prop({ required: true })
password!: string
@Field(_type => [LiftMax])
@prop({
required: true,
type: () => [LiftMax]
})
liftMaxes!: LiftMax[]
//! FIRST CIRCULAR REFERENCE
@Field(_type => [ProgramTemplate])
@prop({
required: false,
ref: () => ProgramTemplate,
type: () => [String],
})
programTemplates!: Ref<ProgramTemplate, string>[]
} As you can see, User has a field Model ProgramTemplate: @ObjectType()
@modelOptions({
schemaOptions: {
timestamps: true
}
})
export class ProgramTemplate {
//! SECOND CIRCULAR REFERENCE
@Field(type => User)
@prop({
required: false,
ref:() => User,
type: () => String,
})
public author!: Ref<User>
@Field(type => User)
@prop({
required: false,
ref: () => User,
type: () => String
})
public owner!: Ref<User>
@Field()
@prop({ required: true })
name!: string;
@Field()
@prop({ required: true })
description!: string;
@Field(type => [Lift])
@prop({
required: true,
ref: Lift,
type: () => [String]
})
public lifts!: Ref<Lift, string>[];
}; Now, ProgramTemplate has a fields I have a ProgramTemplate resolver with field resolvers that resolve most fields with refs to other objects as values. A sample of @Service()
@Resolver(of => ProgramTemplate)
export class ProgramTemplateResolver {
constructor(
private readonly programTemplateService: ProgramTemplateService,
private readonly userRepo: UserRepository,
private readonly liftRepo: LiftRepository
) { }
@Query(of => ProgramTemplatesResponse)
async defaultProgramTemplates(
@Ctx() context: MyContext,
@Arg("type") type: ProgramTemplateType
): Promise<typeof ProgramTemplatesResponse> {
// ...
}
// This will not resolve any of the fields in User which are refs (including User.programTemplates)
@FieldResolver(of => User)
async owner(@Root() template: DocumentType<ProgramTemplate>): Promise<User> {
const user = await this.userRepo.getUser({_id: template.owner as string})
return user!
}
@FieldResolver(of => [Lift])
async lifts(@Root() template: DocumentType<ProgramTemplate>): Promise<Lift[]> {
const liftIds = template.lifts
const lifts = this.liftRepo.getLiftsByIds(liftIds as string[])
return lifts!
}
} The Similarly, If I want to resolve the Here is the @Service()
@Resolver(of => User)
export class UserResolver {
constructor(
private readonly userService: UserService,
private readonly programTemplateRepo: ProgramTemplateRepository
) {}
@UseMiddleware(authUser)
@Query(() => UserResponse)
async me(@Ctx() context: MyContext): Promise<typeof UserResponse> {
// ...
}
@Query(returns => UserResponse, { description: "Returns the a user" } )
async userById(
@Ctx() context: MyContext,
@Arg("id") id: string
): Promise<typeof UserResponse> {
// ...
}
@UseMiddleware(validateInput(RegisterUserInput))
@Mutation(returns => UserResponse)
async registerUser(
@Arg("registerUserParams") registerUserParams: RegisterUserInput,
@Ctx() context: MyContext
): Promise<typeof UserResponse> {
// ...
}
@UseMiddleware(validateInput(LoginUserInput))
@Mutation(returns => UserResponse)
async loginUser (
@Arg("loginUserParams") loginUserParams: LoginUserInput,
@Ctx() context: MyContext
): Promise<typeof UserResponse> {
// ...
}
// This will not resolve any of the fields in ProgramTemplate which are refs (including programTemplates)
@FieldResolver(of => [ProgramTemplate])
async programTemplates(@Root() user: DocumentType<User>): Promise<ProgramTemplate[]> {
const programTemplateIds = user.programTemplates
const templates = await this.programTemplateRepo.getProgramTemplatesByIds(programTemplateIds as string[])
console.log(templates) // None of the ProgramTemplates fields are resolved
return templates
}
} As you can see, So how can I use the existing Resolvers that I wrote for each Model as a FieldResolver for these circular refs of User and ProgramTemplate? Or, what is the best way to handle this kind of situation? Below are two use-cases from the UI that highlight why I'm choosing to use a sort of circular schema. Use cases in UI ( query MyProgramTemplates {
User {
... on Error {
message
}
... on User {
programTemplates {
name
description
type
cycleLength
daysPerWeek
lifts {
name
}
}
}
}
} Sometimes I want to query (from ProgramTemplate) the details of User that exist on the template's query DefaultRoutineSummaries($type: String!) {
defaultProgramTemplates(type: $type) {
... on Error {
message
}
... on ProgramTemplates {
programTemplates {
name
owner {
username
}
description
cycleLength
daysPerWeek
lifts {
name
}
}
}
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Fixed by using repositories to prepopulate dependent data |
Beta Was this translation helpful? Give feedback.
Fixed by using repositories to prepopulate dependent data