0no-co / gql.tada

🪄 Magical GraphQL query engine for TypeScript
https://gql-tada.0no.co
MIT License
2.44k stars 34 forks source link

`turbo` cache is not including fragments that are defined separately (like fragment colocation) #289

Closed dnlsandiego closed 1 month ago

dnlsandiego commented 2 months ago

Describe the bug

It looks like the turbo command isn't including fragments in the generated cache file. Which results in an incomplete graphql-cache.d.ts, breaking types in the editor.

I've created a small repo in the reproduction link. But it's basically the example-pokemon-api in the examples folder. Given:

// ./src/pokemon-item.tsx
export const PokemonItemFragment = graphql(`
  fragment PokemonItem on Pokemon {
    id
    name
  }
`);
// ./src/pokemon.tsx
const PokemonsQuery = graphql(`
  query Pokemons ($limit: Int = 10) {
    pokemons(limit: $limit) {
      id
      ...PokemonItem
    }
  }
`, [PokemonItemFragment]);

Running gql.tada turbo results in a graphql-cache.d.ts that has

declare module 'gql.tada' {
 interface setupCache {
    "\n  query Pokemons ($limit: Int = 10) {\n    pokemons(limit: $limit) {\n      id\n      ...PokemonItem\n    }\n  }\n":
      TadaDocumentNode<{}, { limit?: number | null | undefined; }, { fragment: "Pokemons"; on: unknown; masked: true; }>;
  }
}

PokemonItem is being spread here but it's not included anywhere. Compared to when the fragment is in the same document:

const PokemonsQuery = graphql(`
  query Pokemons ($limit: Int = 10) {
    pokemons(limit: $limit) {
      id
      ...PokemonItem
    }
  }
  fragment PokemonItem on Pokemon {
    id
    name
  }
`, []);
declare module 'gql.tada' {
 interface setupCache {
    "\n  query Pokemons ($limit: Int = 10) {\n    pokemons(limit: $limit) {\n      id\n      ...PokemonItem\n    }\n  }\n  fragment PokemonItem on Pokemon {\n    id\n    name\n  }\n":
      TadaDocumentNode<{}, { limit?: number | null | undefined; }, { fragment: "Pokemons"; on: unknown; masked: true; }>;
  }
}

A warning is also shown

  3:36  The discovered document is not of type "TadaDocumentNode".
        If this is unexpected, please file an issue describing your case.

Reproduction

https://github.com/dnlsandiego/gql.tada-cache-issue

gql.tada version

gql.tada 1.7.0 @0no-co/graphqlsp ^1.12.2

Validations

JoviDeCroock commented 2 months ago

That's odd, somehow TypeScript is refusing to evaluate the symbol in the pokemon-item.tsx file. It finds the type however when we check the symbol the intrinsicName is never and no symbol is assigned, while in the editor it works perfectly fine.

It is odd that the document that the cache produces for you initially is also empty 😅 A bit confused atm as even when I mold this more into our example of examples/example-pokemon-api, which produces correctly for both the query and the fragment, it still doesn't work. Trying to see whether it's some config issue with gql.tada doctor also gave nothing.

One interesting thing is that without the cache the query document node looks like

const PokemonsQuery: TadaDocumentNode<{
    pokemons: ({
        [$tada.fragmentRefs]: {
            PokemonItem: "Pokemon";
        };
        id: string;
    } | null)[] | null;
}, {
    limit?: number | null | undefined;
}, void>

With the cache

const PokemonsQuery: TadaDocumentNode<{}, {
    limit?: number | null | undefined;
}, {
    fragment: "Pokemons";
    on: unknown;
    masked: true;
}>
kitten commented 2 months ago

We had a similar issue before this related to a moduleResolution issue, so we'll likely have to go through tsconfig.json settings and see whether one of them affects the run 🤔

kitten commented 2 months ago

Just a heads up, I haven't forgotten about this, but the behaviour is really odd. The result of gql.tada's graphql calls seems to infer to never unless I symlink my local build of gql.tada into the reproduction. However, my local build is identical to the currently published version, so there seems to be something weird going on with some dependencies.

Edit: This might be related to a bug in either our code or @typescript/vfs' code related to pnpm. When I reinstall all dependencies with Yarn the issues also disappears, so it feels like a resolution bug.

kitten commented 1 month ago

@dnlsandiego: This proved to be hard to reproduce, but it was easy to track down in the end. I'm not sure how we didn't catch this in other reproductions/examples, but it basically came down to a missing realpath resolution, which is required with pnpm