The goal is to use NestJS to implement a GraphQL schema using the code-first approach.
Let's say I have a Pet
type in my GraphQL schema with two fields, name
and age
. If those two pieces of information come from different sources of truth (and I don't always want to fetch both), I could implement a PetResolver
class with resolvers for each field:
@Resolver(() => Pet)
export class PetResolver {
@Query(() => Pet)
pet(): Pet {
return {};
}
@ResolveField()
name(): Promise<string> {
return Promise.resolve('Spot');
}
@ResolveField(() => Int)
age(): Promise<number> {
return Promise.resolve(2);
}
}
which could be used like this:
query GetPet {
pet {
name
}
}
This works and would ensure that the value of each field is only fetched when requested, but what if I wanted to have a pet
field on my User
type that I could query like this:
query GetUserWithPet {
currentUser {
email
pet {
name
}
}
}
Applying the same principle, I could create a UserResolver class like this:
@Resolver(() => User)
export class UserResolver {
@Query(() => User)
@UseGuards(AuthCognitoGuard)
currentUser(@CurrentUser() user: IdTokenPayload): User {
return {
id: user.sub,
email: user.email,
};
}
@ResolveField()
pet(@Parent() user: User): Promise<Pet> {
return petService.getPetForUserId(user.id);
}
}
but then the PetService
implementation would have to be aware of which fields were requested if it only wanted to fetch relevant data.
A) Is there a way to use PetResolver
within UserResolver
to make use of the individual field resolution logic?
B) If not, what is the best way to determine which fields were requested in the query using NestJS code-first conventions?
C) Is this the "wrong" way to think about GraphQL queries? Do best practices dictate that I keep the separate resolver and use a query like this:
query GetUserWithPet {
currentUser {
email
}
pet {
name
}
}
User should contain some petIds
[array] value (internal, DB stored field/column) ...
... making possible to resolve pets: [Pet]
prop/relation - list of Pet
...
... like starshipIDs
explained in https://graphql.org/learn/execution/
Notice: pets service is asked about records using pet ids.
... but of course pet can contain some ownerId
(only or explicitely visible, DB stored field/column) making possible to resolve owner: User
prop [reverse] relation - this way you can:
query PetWithOwner {
pet (id: "someID") {
id
name
owner {
id
email
# more pets?
pets {
id
name
# you can loop it ;)
owner {
id
email
pet.owner
field resolver can return only { id: ownerId }
object (partial response) ... server will try to resolve 'missing' (required by query) email
prop using User
(owner
is User
type) type resolver, passing id as an arg (check/console.log parent
and args
resolver args). You don't have to do it [the same] 'manually' inside pet.owner
field resolver.
... [selection set] can be read from info
object - 4th resolver arg - read docs/tutorial for details