dotansimha / graphql-code-generator

A tool for generating code based on a GraphQL schema and GraphQL operations (query/mutation/subscription), with flexible support for custom plugins.
https://the-guild.dev/graphql/codegen/
MIT License
10.78k stars 1.32k forks source link

`Field(s) ... are not used.` on fields that are used. #10122

Open adriangalilea opened 3 weeks ago

adriangalilea commented 3 weeks ago

Which packages are impacted by your issue?

@graphql-codegen/core

Describe the bug

I want to preface this by saying that I won't provide a repro URL, I don't have the time to so, feel free to close it.

However I crated this mockup code in order to illustrate what the issue is:

async function getBookAvailability(bookIds: string[]): Promise<Record<string, BookAvailability[]>> {
  // Simulate an external API call to get real-time availability data
  // This data couldn't be part of the main GraphQL query as it's dynamic and from a different system
  return bookIds.reduce((acc, id) => {
    acc[id] = [
      { branchId: 'b1', branchName: 'Downtown', availableCopies: Math.floor(Math.random() * 5) },
      { branchId: 'b2', branchName: 'Suburb', availableCopies: Math.floor(Math.random() * 5) },
    ];
    return acc;
  }, {} as Record<string, BookAvailability[]>);
}

export async function getLibraryCatalogSection(sectionId: string) {
  const getCatalogSectionQuery = graphql(`
    query GetCatalogSection($sectionId: ID!) {
      catalogSection(id: $sectionId) {
        id
        name
        description
        books {
          id
          title
          author {
            id
            name
            birthYear
            deathYear
            nationality
          }
          publishYear
          genres
          isbn
          pageCount
          language
          publisher {
            id
            name
            foundedYear
          }
          reviews {
            id
            rating
            reviewText
            userNickname
          }
          coverImage {
            url
            altText
          }
        }
        subSections {
          id
          name
        }
        lastUpdated
        curatorNotes
      }
    }
  `);

  const result = await executeQuery(getCatalogSectionQuery, { sectionId });

  if (!result.catalogSection) return null;

  const bookIds = result.catalogSection.books.map(book => book.id);
  const availabilityData = await getBookAvailability(bookIds);

  const enrichedBooks = result.catalogSection.books.map(book => ({
    ...book,
    availability: availabilityData[book.id] || []
  }));

  return {
    ...result.catalogSection,
    books: enrichedBooks,
  };
}

When I have a query inside of a function where some of the fields are used but the rest are simply returned, I get tons of Field(s) ... are not used. warnings for the fields that are returned to use externally but are not used internally.

It happens for all the fields that I don't access inside the function.

I can't tsignore anything inside graphql(...) so I have no idea how to fix it.

Codegen Config File

import type { CodegenConfig } from "@graphql-codegen/cli";
import dotenv from "dotenv";

const config: CodegenConfig = {
  schema: process.env.GRAPHQL_ENDPOINT,
  documents: ["db/operations/**/*.tsx", "db/operations/**/*.ts"],
  ignoreNoDocuments: true,
  generates: {
    "./db/generated-graphql/": {
      preset: "client",
      presetConfig: {
        fragmentMasking: { unmaskFunctionName: "getFragmentData" },
      },
      config: {
        documentMode: "string",
      },
    },
    "./db/generated-graphql/types.ts": {
      plugins: ["typescript", "typescript-operations"],
      config: {
        enumsAsTypes: false,
        skipTypename: true,
        skipUnusedFragments: true,
      },
    },
    "./db/schema.graphql": {
      plugins: ["schema-ast"],
      config: {
        includeDirectives: true,
      },
    },
  },
};

export default config;
adriangalilea commented 3 weeks ago

Inconvenient solution: if I create the query elsewhere and import it the issue disappears.

bmulholland commented 1 week ago

I'm having a similar problem, but in Vue. Here's an example -- about as bare-bones as one can get for the fragments approach.

<script setup lang="ts">
import { computed } from "vue"
import { gql, useFragment, type FragmentType } from "~typedgql"

const conversationFragment = gql(/* GraphQL */ `
  fragment ConversationHeader_ConversationFragment on Conversation {
    subject
  }
`)

const props = defineProps<{
  conversation: FragmentType<typeof conversationFragment>
}>()

const conversation = computed(() => useFragment(conversationFragment, props.conversation))
</script>

<template>
  <h2>{{ conversation.subject }}</h2>
</template>
Screenshot 2024-09-02 at 10 48 31
bmulholland commented 1 week ago

I managed to find out more about it, and it's likely a separate problem, filed here: https://github.com/dotansimha/graphql-code-generator/issues/10127