gql-dart / ferry

Stream-based strongly typed GraphQL client for Dart
https://ferrygraphql.com/
MIT License
602 stars 116 forks source link

Generating tristate_optionals generates invalid code with mixed up imports #582

Open thomas7D opened 7 months ago

thomas7D commented 7 months ago

I need to use tristate optionals for my mutations and ran into invalid code generation when enabling it.

I recreated the issue in a simple project.

The generated test.var.gql.dart contains errors as it's mixing up the imports when using the tristate classes.

import 'package:ferry_test/__generated__/serializers.gql.dart' as _i1;
import 'package:gql_tristate_value/gql_tristate_value.dart' as _i2;
...
      b..name = const _i2.AbsentValue();
...
if (_$namevalue case _i1.PresentValue(value: final _$value)) {

In some lines it uses the correct import _i2 for the tristate value, in other it's wrong leading to syntax errors.

I haven't figured out what causes this issue as it's not present in all cases. In the example project you can comment out the Pokemons query in lib/test.graphql and the code generation works as expected. But when both query and mutation are present the code is broken.

The same problems also occured in the generated schema files in a larger project when modifying that, with no obvious correlation between the changes in the schema and the mixing of imports.

knaeckeKami commented 7 months ago

Do you also have multiple operations in the same file in your larger project?

thomas7D commented 7 months ago

Yes, I group related queries and mutations for the same objects in a single file.

knaeckeKami commented 7 months ago

Thanks! can you reproduce this issue when you put all operations in a separate file?

thomas7D commented 7 months ago

No, code is fine when I put the mutation in a separate graphql file.

I tested different variations of putting operations in single files, grouping them slightly, etc. and stumbled on this:

If I put both operations in the same file like this, I get the wrong imports prefixes:

query Pokemons {
    pokemons {
        id
        name
    }
}

mutation UpdatePokemon($id: ID!, $name: String) {
    updatePokemon(id: $id, name: $name) {
        id
        name
    }
}

If I switch them around and rerun build_runner, I get no errors in the generated files:

mutation UpdatePokemon($id: ID!, $name: String) {
    updatePokemon(id: $id, name: $name) {
        id
        name
    }
}

query Pokemons {
    pokemons {
        id
        name
    }
}

So I don't think it's related to grouping them or spreading them into separate files.

LiLatee commented 7 months ago

The first problem is here:

image

because of that typeDefNode is always null and then isBuilder is true and it uses replace instead of the value assignment operator (=).

image

And even if originalSymbolName would be fine, in the case of CustomDate it still won't work, because the name of the Node is Date (so the name of the Scalar, not the custom class we've created)

image

Unfortunately, I cannot find any simple way to overcome it for now πŸ€” @knaeckeKami any tips?

LiLatee commented 7 months ago

Ok, I think I found a solution with the use typeOverrides map, but I need to check it. I will back to you

LiLatee commented 7 months ago

Hm I am a little bit blocked. I think the problem is that during generating schema.schema.gql.dart file it uses 2 different allocators for input classes and input serializer classes. I also think that the error is inside ferry_generator package, because generating the code with the use of clean gql_builder works fine and it only breaks when using ferry_generator. But unfortunately, I am not so familiar with that code and cannot spot the error πŸ€”

knaeckeKami commented 7 months ago

Ok, no worries, I'll take a look at it. I also think it's related to the Allocators.

LiLatee commented 7 months ago

I think I found it πŸ˜ƒ I can create PR soon πŸ‘Œ

LiLatee commented 7 months ago

Here is the fix https://github.com/gql-dart/ferry/pull/583 for the aforementioned issue (Test fails 😞 ) and another fix is here https://github.com/gql-dart/gql/pull/448

cprime commented 1 month ago

Any updates on this? I was hoping to use tristate_optionals but this issue is currently blocking me.

LiLatee commented 4 weeks ago

@cprime Unfortunately, I haven't had time to revisit it and fix the tests yet. Currently, I am using a fork with some fixes. You can try these:

dev_dependencies:
  ## We use our custom version of ferry_generator with fixed `tristate_optional` feature.
  ferry_generator:
    git:
      ref: b3c08b68cccc0f18c59b7fc816bdacb45a7303de
      url: https://github.com/lilatee/ferry.git
      path: packages/ferry_generator

dependency_overrides:
  ## We use our custom version of `gql_build` and `gql_code_builder` with somehow fixed `tristate_optionals` feature.
  gql_build:
    git:
      ref: 7edbf44ec1c929a1ed1a9e8e79ca8949ba1ed843
      url: https://github.com/LiLatee/flutter_gql.git
      path: codegen/gql_build
  gql_code_builder:
    git:
      ref: 7edbf44ec1c929a1ed1a9e8e79ca8949ba1ed843
      url: https://github.com/LiLatee/flutter_gql.git
      path: codegen/gql_code_builder
  gql_tristate_value:
    git:
      ref: 7edbf44ec1c929a1ed1a9e8e79ca8949ba1ed843
      url: https://github.com/LiLatee/flutter_gql.git
      path: codegen/gql_tristate_value