Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codegen forces resolution of relationships even if they aren't requested in the query #9973

Closed
asharnadeem opened this issue May 11, 2024 · 2 comments
Assignees

Comments

@asharnadeem
Copy link

Is your feature request related to a problem? Please describe.

The Resolvers type generated by typescript-resolvers does not allow for resolving relationships on the types nested resolver, but forces you to fill them in on the base query, even if it was not requested. For example, if a book must have an author, codegen types will make you return the author even if it was not requested

In database terms, its okay to call and return all the fields from a base table and have graphql filter out what it doesn't need and send it to the client, but having to join every possible relationship an entity could have and return them all is highly inperformant, and kills the point of GraphQL.

Describe the solution you'd like

Let's assume the following schema, where a book must have an author.

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

  type Author {
    id: ID!
    name: String!
  }

  type Book {
    id: ID!
    name: String!
    authorId: ID!
    author: Author!
  }

I should be able to do the below, where I get just the base book on the book query, and can fill in the author on the subresolver if it was requested by the client.

export const resolvers: Resolvers = {
  Query: {
    book: (_, { id }) => ({
      id,
      name: "Book",
    }),
  },
  Book: {
    author: async ({ authorId }) => await getAuthor(authorId),
  },
};

async function getBook() {
  return {
    id: "1",
    name: "Book",
  };
}

async function getAuthor(id: string) {
  return [
    { id: "1", name: "John Doe" },
    { id: "2", name: "Jane Doe" },
  ].find((author) => author.id === id)!;
}

Describe alternatives you've considered

No response

Is your feature request related to a problem? Please describe.

No response

@eddeee888
Copy link
Collaborator

Hi @asharnadeem ,

To achieve what you need, mappers can be used.

Using base plugins

Here's what you can do if you use @graphql-codegen/typescript-resolvers

  1. Create a type that you want to return into a Book type in the schema e.g.
// src/mappers.ts

export type BookMapper = {
  id: string;
  name: string;
}
  1. Then, wire it up in codegen config:
// codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: '**/schema.graphql'
  generates: {
    'src/types.generated.ts': {
      plugins: ['typescript', 'typescript-resolvers'],
      config: {
        mappers: {
          Book: './mappers#BookMapper'
        }
      }
    }
  }
}

export default config;
  1. Run codegen and you can now return BookMapper in Query.book

Using Server Preset

Using base plugin can get repetitive and it also doesn't provide runtime safety. We recommend using Server Preset to get a more managed experience so you can focus more on developing features instead of worrying about types.

To set up server preset, here's what you do:

  1. Update codegen config
// codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli';
import { defineConfig } from '@eddeee888/gcg-typescript-resolver-files';

const config: CodegenConfig = {
  schema: '**/schema.graphql'
  generates: {
    'src/schema': defineConfig(),
}

export default config;
  1. Make sure you schema is in the right module e.g.
# src/schema/schema.graphql
type Query {
  book(id: ID!): Book!
}
# ... other types
  1. Add mappers into schema:
// src/schema/schema.mappers.ts
export type BookMapper = {
  id: string;
  name: string;
}
  1. Run codegen and mappers you can use BookMapper resolver.

Here's the full guide to integrate Server Preset into GraphQL Yoga or Apollo Server

@eddeee888 eddeee888 self-assigned this May 13, 2024
@eddeee888
Copy link
Collaborator

Hi @asharnadeem , I'll close this issue as it's an expected behaviour. If you have issues using mappers or Server Preset, please create other issues and ping me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants