3

I've already posted this as an issue in the graphql-tag repositoy but I'll post it here as I hope somebody on here has a workable solution.

What am I trying to do?

I'd like to dynamically define typedefs of local types based on props passed to my react component.

Why am I doing this?

I realise this is not the intended way of defining gql, however, I'm in the process of creating a React wrapper component around the Apollo Provider. The purpose of it is to make the process of mocking out data locally (as described here https://www.apollographql.com/docs/react/development-testing/client-schema-mocking/) more seamless with less boilerplate. I'm going for a declarative approach where the user can simply define an array of fields (name, graphQL type and optional implementation that will default to a sensible faker implementation for the graphQL type) that will make local fields available directly on the Query type as well as an array of types (name, fields and an optional nested type) which should make it possible to define arbitrary local schemas declaratively with no boilerplate.

What's the outcome at the moment?

Just to establish a baseline, the following is working just fine and allows me to run codegeneration from Apollo CLI and query the new local test field (with a @client directive) in my application

  const localTypeDefs = gql`
    extend type Query {
      test: String
    }
  `;

  const client = new ApolloClient({
    cache: new InMemoryCache(),
    uri: "https://localhost:4000/graphql",
    typeDefs: localTypeDefs,
    ...apolloClientOptions,
  });

If I change the qgl definition to look like this instead

  const name = "name";
  const graphQLType = "String";

  const localTypeDefs = gql`
    extend type Query {
      ${name}: ${graphQLType}
    }
  `;

I get the following error when running codegen Syntax Error: Expected Name, found ":". If I change the gql definition to this

  const testString = "test: String";

  const localTypeDefs = gql`
    extend type Query {
      ${testString}
    }
  `;

I get this error Syntax Error: Expected Name, found "}". on codegen. In general, it seems like everything after the interpolated string causes the compiler to emit this error on the next character. If I include the } in the testString, I get the error Syntax Error: Expected Name, found <EOF>..

Now, If I try to change to the function syntax instead so the localTypeDefs definition looks as follows:

  const testString = "test: String";

  const localTypeDefs = gql(`extend type Query { ${testString} } `);

The typedef is actually generated without any error, however, the codegeneration still fails with the error GraphQLError: Cannot query field "test" on type "Query" when I query for this field. The query hasn't change at all from the working baseline I posted at the top and if I change back to that without touching anything else, the codegen no longer complains about the query. Curiously, if I change the above back to the baseline implementation but keep the explicit function call instead of the implicit `` string as the following:

const localTypeDefs = gql(`
    extend type Query {
      test: String
    }
  `);

I still get the error GraphQLError: Cannot query field "test" on type "Query" but as soon as I change back to the base case, everything is working just fine.

Niklas Moss
  • 61
  • 1
  • 7
  • I wonder if the built in "gql" even accepts additional arguments for its template literal, or if perhaps you could extend the existing gql and make your own custom arguments for it, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals. I'd guess something like this might be a reason why the function calls suddenly give different errors. –  Nov 02 '21 at 12:58

1 Answers1

2

I was was able to get something similar to this working for a query by wrapping an input with double quotes:

 const query = gql`
    mutation RegenerateAgreement {
      agreementsRegenerate(input: { userId: "${userId}" }) {
        agreements {
          body
          prompt          
        }
      }
    }
  `;

6xth
  • 87
  • 5