eddeee888 / graphql-code-generator-plugins

List of GraphQL Code Generator plugins that complements the official plugins.
MIT License
51 stars 12 forks source link

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

Open gio-shara-code opened 1 year ago

gio-shara-code commented 1 year ago

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: graphql@16.6.0/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

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/graphql@16.6.0/node_modules/graphql/language/location.js:23:30)
    at /Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/graphql@16.6.0/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/graphql@16.6.0/node_modules/graphql/error/GraphQLError.js:127:25)
    at SchemaValidationContext.reportError (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/graphql@16.6.0/node_modules/graphql/type/validate.js:73:7)
    at validateFields (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/graphql@16.6.0/node_modules/graphql/type/validate.js:271:13)
    at validateTypes (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/graphql@16.6.0/node_modules/graphql/type/validate.js:244:7)
    at validateSchema (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/graphql@16.6.0/node_modules/graphql/type/validate.js:43:3)
    at assertValidSchema (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/graphql@16.6.0/node_modules/graphql/type/validate.js:56:18)
    at ApolloServer.generateSchemaDerivedData (/Users/gioshara/Youtube/code-for-videos/social-media/backend-clone/node_modules/.pnpm/@apollo+server@4.7.3_graphql@16.6.0/node_modules/@apollo/server/dist/cjs/ApolloServer.js:333:41)

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

gio-shara-code commented 1 year ago

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!
}
eddeee888 commented 1 year ago

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)

nickqweaver commented 1 year ago

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.

asgerjensen commented 1 year ago

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

tenpaiyomi commented 11 months ago

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.

theomessin commented 10 months ago

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

theomessin commented 10 months ago

@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?

konhi commented 8 months ago

@theomessin how silly, literally what happened to me too πŸ™ˆ perhaps more meaningful errors might be helpful

eddeee888 commented 8 months ago

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