graphqlnestjs

Get list of requested keys in NestJS/GraphQL request


I am just fiddling around trying to understand, thus my types are not exact.

@Resolver()
export class ProductsResolver {
    @Query(() => [Product])
    async products() {
        return [{
            id: 55,
            name: 'Moonshine',
            storeSupplies: {
                London: 25,
                Berlin: 0,
                Monaco: 3,
            },
        }];
    }
}

If I request data with query bellow

{
    products{
      id,
      name,
    }
}

I want async carriers() to receive ['id', 'name']. I want to skip getting of storeSupplies as it might be an expensive SQL call.


I am new to GraphQL, I might have missed something obvious, or even whole patterns. Thanks in advance.


Solution

  • Another option is to directly use the @Info decorator provided by NestJS, as found here: https://docs.nestjs.com/graphql/resolvers-map#decorators

    It could look something like this:

    @Resolver()
    export class ProductsResolver {
        @Query(() => [Product])
        async products(
        @Info() info
        ) {
            // Method 1 thanks to @pooya-haratian.
            // Update: use this method; read below article to understand why.
            let keys = info.fieldNodes[0].selectionSet.selections.map(item => item.name.value);
            // Method 2 by me, but I'm not sure which method is best.
            // Update: don't use this; read below article to understand why.
            let keys = info.operation.selectionSet.selections[0].selectionSet.selections.map(field => field.name.value);
            return keys;
        }
    }
    

    Update: After reading this article on GraphQL Server Basics: Demystifying the info Argument in GraphQL Resolvers, I have learned that fieldNodes is an excerpt of the Abstract Syntax Tree (AST), while operation is the AST of the entire query.

    As for why it's safe to select the first object in the array of fieldNodes (fieldNodes[0]), it is because the excerpt starts at the current field, as opposed to the root of the query.

    Hence, @pooya-haratian's method was correct. I simply added the elaboration and used NestJS's decorator (@Info).