graphql-code-generator-plugins icon indicating copy to clipboard operation
graphql-code-generator-plugins copied to clipboard

[BUG] Server Preset is not validating schemas in before running codegen

Open 0xCodeMaieutics opened this issue 2 years ago • 9 comments

Describe the bug I am following this article here: https://the-guild.dev/graphql/codegen/docs/guides/graphql-server-apollo-yoga-with-server-preset. I want to generate resolver and schema types (typedefs) with the following library: @eddeee888/gcg-typescript-resolver-files. Schema and resolver type generation works fine, but when I am trying to run the apollo server with the generated typedefs it throws and error (See error below). The error is thrown from the following path: [email protected]/node_modules/graphql/language/location.js:23 to be more precise this function throws it getLocation.

function getLocation(source, position) {
  let lastLineStart = 0;
  let line = 1;

  for (const match of source.body.matchAll(LineRegExp)) { // body is apparently not defined if you take a close look into the error message
    typeof match.index === 'number' || (0, _invariant.invariant)(false);

    if (match.index >= position) {
      break;
    }

    lastLineStart = match.index + match[0].length;
    line += 1;
  }

  return {
    line,
    column: position + 1 - lastLineStart,
  };
}

Would appreciate your help, thanks.

To Reproduce _Steps to reproduce the behavior: _1. Create apollo server 4 _2. Create sample graphql query _3. Generate types using @eddeee888/gcg-typescript-resolver-files _4. Pass generated resolvers and typedefs to the server. _5. Run the server

Expected behavior Should be running server smoothly without throwing the error (see below)

Versions

  • Node: 18.15.0
  • Apollo server: ^4.7.3
  • Graphql: ^16.6.0

Additional context Minimal code below:

import { ApolloServer, BaseContext } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
import { typeDefs } from "./schema/typeDefs.generated";
import { resolvers } from "./schema/resolvers.generated";

const server = new ApolloServer<BaseContext>({
  typeDefs, // throws error
  resolvers,
});

startStandaloneServer(server, {
  listen: { port: 4000 },
}).then(({ url }) => console.log(`🚀  Server ready at ${url}`));

Error message:

TypeError: Cannot read properties of undefined (reading 'body')
    at getLocation (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/[email protected]/node_modules/graphql/language/location.js:23:30)
    at /Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/[email protected]/node_modules/graphql/error/GraphQLError.js:128:39
    at Array.map (<anonymous>)
    at new GraphQLError (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/[email protected]/node_modules/graphql/error/GraphQLError.js:127:25)
    at SchemaValidationContext.reportError (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/[email protected]/node_modules/graphql/type/validate.js:73:7)
    at validateFields (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/[email protected]/node_modules/graphql/type/validate.js:271:13)
    at validateTypes (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/[email protected]/node_modules/graphql/type/validate.js:244:7)
    at validateSchema (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/[email protected]/node_modules/graphql/type/validate.js:43:3)
    at assertValidSchema (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/[email protected]/node_modules/graphql/type/validate.js:56:18)
    at ApolloServer.generateSchemaDerivedData (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/@[email protected][email protected]/node_modules/@apollo/server/dist/cjs/ApolloServer.js:333:41)

Note: I am using the exact same folder structure as in the documentation.

0xCodeMaieutics avatar Jun 11 '23 09:06 0xCodeMaieutics

Solution

Okay, apparently this library does not like when you don't have mutation resolvers at all. For some reason it throws the above described error, because I did not implement at least one mutation throughout schemas...

extend type Query {
  book(id: ID!): Book
}

extend type Mutation {
  markBookAsRead(id: ID!): Book! # added this mutation and generated types.
}

type Book {
  id: ID!
  isbn: String!
}

0xCodeMaieutics avatar Jun 11 '23 10:06 0xCodeMaieutics

Hi @gio-shara-code,

You are right about the extend type Mutation 🙂 It looks like the preset's not validating and throwing error if the schema is invalid.

I think in this case, there are one of two ways (one of which you covered):

  1. Remove the type Mutation
  2. Add the extend type Mutation with at least one field (Your solution)

I think the solution here is to for the preset to see validate the parsed schema. Thanks for reporting the issue and the solution! 🙌


(Note that codegen will validate the schema when running plugins if the documents option is set. However, we don't usually set this option when generating server types... so it could be a problem if we generate server type without the preset too)

eddeee888 avatar Jun 13 '23 10:06 eddeee888

I was getting this exact same error but had declared both at least 1 Mutation and 1 Query. Turns out I accidentally added the extends keyword in front of one of my schema types. Seems like this should fail on code generation instead of attempting to validate the schema with invalid type defs when there is no schema type to extend.

nickqweaver avatar Jul 10 '23 23:07 nickqweaver

Isnt the primary issue here, that the typedefs dont set the source element, so the graphql/language/location.js breaks?

At least for me, that seems to be the biggest hurdle, because it is hiding the underlying schema problem

asgerjensen avatar Oct 06 '23 10:10 asgerjensen

I'm running into this issue, but the proposed solution is actually not working for me. In fact, it seems when I do create Mutations is when it breaks. If can have a set of schemas with the base/schema.graphql having type Mutation commented out and the extend type Mutation commented out in my various other queries and it works, but as soon as I uncomment the type Mutation and any of the extend type Mutation then the whole thing breaks.

tenpaiyomi avatar Nov 04 '23 00:11 tenpaiyomi

@tenpaiyomi Having the same issue as you. Did you figure out how to solve this?

theomessin avatar Dec 04 '23 14:12 theomessin

@tenpaiyomi I had a silly mistake with my mutation, was using a type as an input to my mutation which doesn't work 🤦🏼 Works fine now. Maybe you have some mistake with one of your mutations too?

theomessin avatar Dec 05 '23 10:12 theomessin

@theomessin how silly, literally what happened to me too 🙈 perhaps more meaningful errors might be helpful

konhi avatar Jan 27 '24 18:01 konhi

Hi all, thanks for reporting this, I'll take a look soon to see what the best solution is 😊

eddeee888 avatar Feb 07 '24 11:02 eddeee888