-
Notifications
You must be signed in to change notification settings - Fork 125
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] Add immutability features #35
Comments
The data class is just a viewer on top of a serialized JSON, so you can "serialize" it by calling To me it feels like That said, I'm happy to hear more about concrete examples where our data getters fall short. One known issue is that field values get instantiated on every read. But we can get around it by caching values on first read. |
another option: |
I'm using
Other than that, syntax and maturity are the major differences. |
@micimize It was some time ago, but I felt that json serializable is incompatible with what we need here. Has it worked well for you? If I remember correctly, it was about the possibility of representing optional field arguments variables. |
I'd like to do some work on adding immutability features to the builders, starting with From my perspective, the following are important features that are currently missing from generated data classes:
@micimize @klavs is there any other functionality that you'd want to see in generated data classes?
Freezed's late functionality seems like it'd solve this issue. |
@smkhalsa, at this point I do not have any codegen project to guide me so I'm happy to give you the ownership of the codegen packages. I've been doing some GraphQL codegen in the JS-land recently and I've found that using simple String templates are easier to use than the builder pattern. Using |
I ran into no real issues using Idk how much "leaner" Serialization and thus custom scalar support is important to me – not sure where that currently stands. If the models are meant to be instantiable then I eventually want to get to a fully typed cache that is essentially a partial of the remote schema, which means
|
I also use string templating in one major tick in |
Freezed doesn't support implementing interfaces from other freezed classes, which will be an issue since we rely on interfaces to implement fragments / unions. |
If that's needed, Freezed could generate the methods as extensions instead of methods. This should allow things like: @freezed
abstract class Tiny with _$Tiny {
factory Tiny({ String name }) = _Tiny;
}
@freezed
abstract class Small with _$Small implements Tiny {
factory Small({ String name, int age }) = _Small;
} |
@rrousselGit Thanks for chiming in here.
I've started working on incorporating |
@rrousselGit I'm running into some issues using |
I'll give this a look tomorrow, I have to think this through just in case. Would you mind describing why you need that in the first place? |
Sure. Here's some example code that class $AllSongsQuery {
const $AllSongsQuery(this.data);
final Map<String, dynamic> data;
List<$AllSongsQuery$Song> get Song => data['Song'] == null
? null
: (data['Song'] as List)
.map((dynamic e) => $AllSongsQuery$Song((e as Map<String, dynamic>)))
.toList();
}
class $AllSongsQuery$Song implements $SongFragment {
const $AllSongsQuery$Song(this.data);
final Map<String, dynamic> data;
String get id => (data['id'] as String);
String get name => (data['name'] as String);
String get fileUrl => (data['fileUrl'] as String);
String get imageUrl => (data['imageUrl'] as String);
String get albumName => (data['albumName'] as String);
String get artistName => (data['artistName'] as String);
}
class $AudioFragment {
const $AudioFragment(this.data);
final Map<String, dynamic> data;
String get id => (data['id'] as String);
String get name => (data['name'] as String);
String get fileUrl => (data['fileUrl'] as String);
}
class $SongFragment implements $AudioFragment {
const $SongFragment(this.data);
final Map<String, dynamic> data;
String get id => (data['id'] as String);
String get name => (data['name'] as String);
String get fileUrl => (data['fileUrl'] as String);
String get imageUrl => (data['imageUrl'] as String);
String get albumName => (data['albumName'] as String);
String get artistName => (data['artistName'] as String);
} |
We may be able to get away with only building However, there may be edge cases where this doesn't work (e.g. if the user for some reason needs to be able to instantiate a GraphQL fragment class). |
I don't quite understand. What would that code looks like with freezed, and why is it generated this way? |
With freezed, it would look something like: @freezed
abstract class AllSongsQuery with _$AllSongsQuery {
factory AllSongsQuery({
List<AllSongsQuery$Song> Song,
}) = _$AllSongsQuery;
}
@freezed
abstract class AllSongsQuery$Song
with _$AllSongsQuery$Song
implements SongFragment {
factory AllSongsQuery$Song({
String id,
String name,
String fileUrl,
String imageUrl,
String albumName,
String artistName,
}) = _$AllSongsQuery$Song;
}
@freezed
abstract class AudioFragment with _$AudioFragment {
factory AudioFragment({
String id,
String name,
String fileUrl,
}) = _$AudioFragment;
}
@freezed
abstract class SongFragment with _$SongFragment implements AudioFragment {
factory SongFragment({
String id,
String name,
String fileUrl,
String imageUrl,
String albumName,
String artistName,
}) = _$SongFragment;
} This allows common usage of data fetched using different GraphQL queries. For example, we might also have a |
@rrousselGit rrousselGit/freezed#70 looks like it will also be an issue for us. Since we are generating freezed classes based on the user-defined graphql models, we cannot guarantee that there won't be collisions. |
I don't mind solving it, but I am not aware of any simple solution. This is something that all code-generators suffers from. |
gql_build uses |
I think It looks like |
Yeah, but that falls in the "not so simple category"
It's quite tedious, as it's not solved in a single location and needs to be
done every time we want to use a type.
I can easily see me forgetting one type in a specific part of the generated
code. So I need to think this through
Le jeu. 14 mai 2020 à 15:52, Michael Joseph Rosenthal <
[email protected]> a écrit :
… I think Allocator is for referencing imports in generated code, whereas
the freezed issue is about referencing user imported libraries with
aliases.
It looks like built_value parses the library's ast
<https://github.com/google/built_value.dart/pull/703/files#diff-e86ce28f4538fe998a497569897b4a33>.
I revived an issue on source_gen asking for a generic solution/recipe
dart-lang/source_gen#462
<dart-lang/source_gen#462>
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#35 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AEZ3I3IAW3VHBLDSLD3RHPTRRQATFANCNFSM4KIWM7FQ>
.
|
closed in #110 |
I just wanted to start a discussion about the possibility of building data as built_values rather than storing the Json object and using getters.
I find the immutability and serializability of built_value to be compelling, although it would add some complexity.
Thoughts?
The text was updated successfully, but these errors were encountered: