1
votes

I am writing a backend application that uses type-graphql. The GraphQL schema includes a Folder type that looks like this:

type Folder {
  id: ID!
  name: String!
  rules: [Rule!]!
  parent: Group
}

Rule and Group are other types.

My Resolver defines a Query called folders that returns all Folders:

import {Query, Resolver} from 'type-graphql'

@Resolver(() => Folder)
export default class FolderResolver {

  @Query(() => [Folder])
  folders(): Promise<Folder[]> {
    // query db and return results
  }
}

To query the folders, their rules, and their parent group from the database, I have to join the database tables and return the joined result, which works without problems. However: If the rules field and / or the parent field was not requested in the GraphQL query, I could omit the joins and make the database query much more efficient. So the fields that were requested in the GraphQL query have a definite effect on the logic that I need to execute, but I don't see a way of finding out which fields were requested inside the folders function.

When a Query in a type-graphql Resolver is executed, is there a way to determine which fields were requested in the GraphQL query?

1

1 Answers

3
votes

Have a look at Field Resolver. The annotation is specifically made for such purpose

import {Query, Resolver, FieldResolver} from 'type-graphql'

@Resolver(() => Folder)
export default class FolderResolver {

  @FieldResolver()
  rules(@Root() folder: Folder) {
    // ...
  }


  @FieldResolver()
  parent(@Root() folder: Folder) {
    // ...
  }

  @Query(() => [Folder])
  folders(): Promise<Folder[]> {
    // query db and return results
  }
}

Now, when a user requests a query without rules or parent as a part of their attributes, they won't be called, if they do either or both will be called. Your logic to fetch data for them resides in their own field resolvers.


Updated as per comment:

If you have to get fields queries by the clients, you may use a library like graphql-fields. This helps you to extracts fields from the info parameter of the resolver function. Something like this: (as mentioned in the docs)

  import graphqlFields from 'graphql-fields';

  @Query(() => [Folder])
  folders(@Info() info: GraphQLResolveInfo): Promise<Folder[]> {
    // get fields
    const topLevelFields = Object.keys(graphqlFields(info));
    // query db and return results
  }

Now you can run your query based on the requested fields.