Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

Add an option to create classes that include a superset of fields from all fragments #264

Open
euriasb opened this issue Feb 26, 2021 · 4 comments

Comments

@euriasb
Copy link

euriasb commented Feb 26, 2021

This is better explained with an example, let's say you have the following GraphQL class:

User
- id
- name
- email
- facebook_account
- instagram_account
- ...some other fields

And you have these fragments and queries

fragment BasicUserData {
  id
  name  
  email
}

fragment SocialUserData {
  ...BasicUserData
  facebook_account
  instagram_account
}

query BasicQuery {
  basicUser(id: ID) {
    ...BasicUserData
  }
}

query AdvancedUserQuery1 {
  advancedUser1(id: ID) {
    ...SocialUserData
    *some other fields*
  }
}

query AdvancedUserQuery2 {
  advancedUser2(id: ID) {
    ...SocialUserData
   *some other fields*
  }
}

This would generate a BasicUserDataMixin and a SocialUserDataMixin.
BasicQuery would return an object of type BasicQuery$RootQuery$User which implements BasicUserDataMixin.
AdvancedUserQuery1 would return and object of type AdvancedUserQuery1$RootQuery$User which implements both Mixins, and AdvancedUserQuery2 would return and object of type AdvancedUserQuery2$RootQuery$User which also implements both Mixins.

Now, let's say I have a shared widget which renders basic and social media data for a user and it can be used from parent widgets which perform AdvancedUserQuery 1 and 2, since I need both basic and social data my widget needs both Mixins, but since dart doesn't have union types there is no way to specify that, and since it is used from different parents I also cannot specify the concrete type.

My proposal is to generate classes containing the properties from fields that are included in all fragments, and use those as the return types for all queries, with the fields not queried set to null, so in this case you would generate

class User {
  String id;
  String name;
  String email;
  String facebook_account;
  String instagram_account;
  *all other queried fields*
}

And all three queries would return a User object.

Note that this was the approach that Facebook used at least in the internal GraphQL sdks, not sure what they released publicly.

@vasilich6107
Copy link
Collaborator

vasilich6107 commented Feb 28, 2021

@comigor technically this could be solved by flattening nested fragments from the same object

@comigor
Copy link
Owner

comigor commented Feb 28, 2021

As far as I understand, that's similar to my proposal of canonical types generation. The User class you're proposing is basically the canonical (1:1 match with schema's class with all nullable fields). However, this is not as easy as it seems, specially when you try to deal with interfaces and union types.

@euriasb
Copy link
Author

euriasb commented Mar 1, 2021

Yes, it sounds like it's the same thing. Could be possible to add some version of this, even if it doesn't support all cases like interfaces and unions as you mention?

@comigor
Copy link
Owner

comigor commented Mar 1, 2021

My issue with shipping a version without considering some cases is to create a huge breaking change. Yesterday I did work on that proposal again and it already changed a lot. Even in beta, it's not that good to create a lot of breakingn changes.

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

No branches or pull requests

3 participants