Field resolvers with TypeGraphQL

The GraphQL query language is becoming more popular these days, a lot of projects and engineers have already discovered the opportunity and the beauties of this tool in the context of API design. If you are new in this field, I strongly recommend you to read more about this topic because you can have a lot of benefit from it.

In this article, I am going to cover only a small part of the GraphQL API design and I am going to inspect it from a view of a specific tool, the TypeGraphQL.

What is a TypeGraphQL?

TypeGraphQL is a framework that makes the typed GraphQL API layer building easier. GraphQL is not JavaScript specific, it is not part of a programing language but it is a specification for a unique API layer. There are many implementations on the market in different languages with different tools and frameworks, making it possible to write GrqphQL APIs in your favorite programming language. TypeGraphQL is one of them. It is written in Typescript which makes it possible to write the QraphQL service layer in Typescript painless.

What is a field resolver in GraphQL?

A field resolver is the resolver of one specific field in the GraphQL service. A GraphQL query can return not only primitive data types, like String, Number, Boolean, etc. but it is possible to define how should the query handle if a client requests a more sophisticated field, like an object or an array, and what if the object has also an object property, and so on. The field resolver can be even more complex if a specific field needs an async method call, like a database query or a third-party API call to get the return value. In the GraphQL documentation it looks like this:

Query: {
  human(obj, args, context, info) {
    return context.db.loadHumanByID(args.id).then(
      userData => new Human(userData)
    )
  }
}

Field resolver implementation in TypeGraphQL

If we want to implement a field resolver with an async operation in it, we can do it like this:

@Resolver(of => Author)
class AuthorResolver {
  @FieldResolver(() => [Post])
  async posts(@Root() author: Author, @Ctx() ctx: Context): Promise<Post[]> {
    const posts = await ctx.prisma.post.find({ where: { ownerId: author.id } });
    if (!posts) throw new SomethingWentWrongError();
    return posts;
  }
}

This is a Resolver that resolves our author entity. This author has a posts field that supposed to return every post made by the specified author. I am using Prisma in this example as a database ORM. Prisma connects the database to the NodeJS backend application and makes it easy to load data from it. Of course, it is not required for the TypeGraphQL field resolver, so you can use any ORM or API, which is the best fit for you.

In the next step let’s make our resolver a bit smarter. Make it possible to add arguments to filter the result by labels for example.

@Resolver(of => Author)
class AuthorResolver {
  @FieldResolver(() => [Post])
  async posts(
    @Root() author: Author, 
    @Arg('labels', { nullable: true }) labels: string[], 
    @Ctx() ctx: Context
    ): Promise<Post[]> {
    const posts = await ctx.prisma.post.find({ 
        where: { 
            ownerId: author.id, 
            labels: { 
                hasSome: labels 
            } 
        } 
    });
    if (!posts) throw new SomethingWentWrongError();
    return posts;
  }
}

The second argument means the client can specify strings as labels, and the field resolver returns only that posts which contain at least one of the labels. This argument is nullable, so if the client doesn’t specify any labels, the field resolver returns all posts by the author.

If we want to call this query from the client we need to define a query something like below. In this particular query, we load every post by an author labeled as "software" or "web development".

query {
  author(name: "Author John") {
    id
    posts(labels:["software", "web development"]) {
      id
      title
    }
  }
}

Summary

In this short post, we saw what is the field resolver means and how we can implement it with TypeGraphQL. GraphQL is a powerful tool to build complex API layers and one part of this is the field resolver. This solution makes possible to define resolver methods for object fields, making the layer organized and improving the developer experience.