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

[gql_build] ensure all serializer return types (all types?) are available in generated file, or allow import config #143

Closed
danielmahon opened this issue Sep 26, 2020 · 3 comments · Fixed by #148

Comments

@danielmahon
Copy link

danielmahon commented Sep 26, 2020

@smkhalsa Issue created from our DIscord discussion

A custom serializer's return type that is imported from another file is not shown in serializers.gql.dart causing a build error.

Only happens with generated BuiltLists? I have other custom scalars set-up the same way but addBuilderFactory functions are not generated for them so this problem doesn't occur...

Also, the addBuilderFactory function is generated multiple times...

Note: build_runner build is still successful

Error

lib/graphql/schema/serializers.gql.g.dart:182:59: Error: Getter not found: 'MyModel'.
          const FullType(BuiltList, const [const FullType(MyModel)]),
                                                          ^^^^^^^^^^^^^^
lib/graphql/schema/serializers.gql.g.dart:183:33: Error: 'MyModel' isn't a type.
          () => new ListBuilder<MyModel>())
                                ^^^^^^^^^^^^^^

Example

# schema.g.graphql
#...
"""JSON encoded custom scalar type"""
scalar MyModelPlural

type Foo {
  id: String!
  items: [MyModelPlural!]
}
#...
# build.yaml
#...
      ferry_generator|req_builder:
        enabled: true
        options:
          schema: flutter_app|lib/graphql/schema/schema.g.graphql
          type_overrides:
            MyModelsPlural:
              name: MyModel
              import: 'package:flutter_app/models/my_model.dart'
      gql_build|serializer_builder:
        enabled: true
        options:
          schema: flutter_app|lib/graphql/schema/schema.g.graphql
          custom_serializers:
            - import: 'package:flutter_app/graphql/serializers/my_model_serializer.dart'
              name: MyModelSerializer
#...
// my_model_serializer.dart

// ignore: implementation_imports
import 'package:gql_code_builder/src/serializers/json_serializer.dart';

// This import exposes "MyModel" which will be required, but missing, from serializers.gql.dart
import 'package:flutter_app/models/my_model.dart';

class MyModelSerializer extends JsonSerializer<MyModel> {
  @override
  MyModel fromJson(Map<String, dynamic> data) {
    return MyModel.fromJson(data);
  }
  @override
  Map<String, dynamic> toJson(MyModel model) {
    return model.toJson();
  }
}
// serializers.gql.dart

//...
// Correctly exposes "MyModelSerializer" but NOT "MyModel", causing built file to have missing type
import 'package:flutter_app/graphql/serializers/my_model_serializer.dart'
    show MyModelSerializer;

part 'serializers.gql.g.dart';

final SerializersBuilder _serializersBuilder = _$serializers.toBuilder()
  ..add(OtherSerializer())
  ..add(MyModelSerializer())
//...
// serializers.gql.g.dart

//...
      ..addBuilderFactory(
          const FullType(BuiltList, const [const FullType(MyModel)]),
          () => new ListBuilder<MyModel>()))
      ..addBuilderFactory(
          const FullType(BuiltList, const [const FullType(MyModel)]),
          () => new ListBuilder<MyModel>()))
     ..addBuilderFactory(
          const FullType(BuiltList, const [const FullType(MyModel)]),
          () => new ListBuilder<MyModel>()))
//...
@danielmahon
Copy link
Author

adding the missing import MyModel into serializers.gql.dart fixes the issue, but I still haven't dug deep enough into built_value to see why/where it's adding those builder factories, and why it's only doing it for the list item and not the other overrides

@smkhalsa
Copy link
Member

@danielmahon built_value generates the serializers.gql.g.dart file based on the contents of your serializers.gql.dart.

I don't actually think this has anything to do with the custom serializer. built_value is building the BuilderFactories because one of your GraphQL operations uses a BuiltList<MyModel>, and BuilderFactories are what tell built_value how to serialize BuiltLists of non-standard types.

The easiest solution would be to just include an import of any type overrides by default. I've created PR #148 which implements this. Can you please confirm that it fixes the issue? NOTE: you will need to include your type_overrides map in the serializer_builder in your build.yaml file.

A more elegant solution that selectively imports the custom types only when they will be used in a BuilderFactory would not be trivial, and I think this solution is probably good enough.

@danielmahon
Copy link
Author

@smkhalsa this works, thank you

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

Successfully merging a pull request may close this issue.

2 participants