-
-
Notifications
You must be signed in to change notification settings - Fork 54
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
Add Back includeIfNullOnInput
build options
#339
Comments
👋 @yuhangang This library is created and maintained by me, @budde377. Please consider supporting my work and ensure our survival by donating here. |
So just to make sure I understand your request. You are migrating your code base and would like a way to declare input where You can declare |
yup, u get my point, sry for my bad English. I considered to declaring to adding |
Your English is fine. Would you consider a new constructor, e.g.
`Input.withNull(…)` as a reasonable alternative?
…On Fri, 1 Mar 2024 at 08:45, YUHANG ANG ***@***.***> wrote:
yup, sry for my bad English.
Yup, I considered to declaring to adding copyWith for each
query/mutation. But it would be good to have a consistent and predictable
way to sending null params to server.
—
Reply to this email directly, view it on GitHub
<#339 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AA2UFSYK2FIHBG7FMRDRODDYWA52JAVCNFSM6AAAAABEBCYA22VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNZSG43DANJRGU>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Yup, that would be more predictable compared to manual handling for each fields |
@budde377 Just curious, instead of an alternative such as |
Everything is possible 🌈 Why do you prefer this option? |
Think it benefits project where there are multiple query/mutation arguments that allows null values, as it omits the need to manually add the |
Having a better solution for this would be preferable! Have you considered trying to use sentinel values? I'm not sure how viable that is though. |
@Kaelten, can you give me an example of what you had in mind? |
Note I'm fairly new to dart, so I'm not sure how crazy of an idea this actually is. I did come up with a few options but they all have draw backs and tradeoffs. I think there are other riffs on these options but they all seem to come back to some version of the following: Optional WrappersIn this version we have to wrap valid values with an object, not great, but it maintains perfect type safety. class Optional<T> {
final T? value;
final bool isUndefined;
Optional(this.value) : isUndefined = false {}
const Optional.undefined()
: value = null,
isUndefined = true;
}
class Input$ProfileInput {
final Optional<String?> displayName;
final Optional<int?> age;
final Optional<String?> email;
Input$ProfileInput({
Optional<String?> displayName = const Optional.undefined(),
Optional<int?> age = const Optional.undefined(),
Optional<String?> email = const Optional.undefined(),
}) : this.displayName = displayName,
this.age = age,
this.email = email;
Map<String, Object?> toMap() {
return {
if (!this.displayName.isUndefined) 'displayName': displayName.value,
if (!this.age.isUndefined) 'age': age.value,
if (!this.email.isUndefined) 'email': email.value,
};
}
}
void main() {
var input = Input$ProfileInput(
displayName: Optional('John Doe'),
email: Optional(null),
);
print(input.toMap());
} Leveraging an Object constantThis method avoids having to wrap every value with an object, but it looses compile time type safety on the constructor while maintaining it within the class at least. class _Undefined {
const _Undefined();
static const instance = _Undefined();
}
class Input$ProfileInput {
final String? displayName;
final int? age;
final String? email;
final Set<String> _definedFields;
Input$ProfileInput({
Object? displayName = _Undefined.instance,
Object? age = _Undefined.instance,
Object? email = _Undefined.instance,
}) : this.displayName =
displayName == _Undefined.instance ? null : displayName as String?,
this.age = age == _Undefined.instance ? null : age as int?,
this.email = email == _Undefined.instance ? null : email as String?,
_definedFields = {
if (displayName != _Undefined.instance) 'displayName',
if (age != _Undefined.instance) 'age',
if (email != _Undefined.instance) 'email',
};
Map<String, Object?> toMap() {
return {
if (_definedFields.contains('displayName')) 'displayName': displayName,
if (_definedFields.contains('age')) 'age': age,
if (_definedFields.contains('email')) 'email': email,
};
}
}
void main() {
var input = Input$ProfileInput(
displayName: 'John Doe',
email: null,
);
print(input.toMap());
} Magic ValuesThis version relies on magic constants to represent undefined values. On the plus side we have perfect type saftey without any cruft, but the con is that we have to have a valid value for all possible fields. In some cases, you might be able to make use of null, but in others config options could be used to specify sentinel values in case negative max int or similar is in fact a valid value. class Input$ProfileInput {
final String? displayName;
final int? age;
final String? email;
static const _undefinedString = r'Input$ProfileInput$__undefined_string';
static const _undefinedInt = -(1 << 53); // max neg int on dart web
Input$ProfileInput({
String? displayName = _undefinedString,
int? age = _undefinedInt,
String? email = _undefinedString,
}) : this.displayName = displayName,
this.age = age,
this.email = email;
Map<String, Object?> toMap() {
return {
if (displayName != _undefinedString) 'displayName': displayName,
if (age != _undefinedInt) 'age': age,
if (email != _undefinedString) 'email': email,
};
}
} |
Thanks, @Kaelten - these are good, well-presented suggestions. I have added a variation of version two, which follows how the When the configuration is enabled by setting Given the schema input Foo {
requiredValue: String!
optionalValue1: String
optionalValue2: String
optionalValue3: String
} the generated class will be final input = Input$Foo((builder) => builder(
requiredValue: "value a",
optionalValue1: "value b",
optionalValue2: null
)); and the generated JSON will be { "requiredValue": "value a", "optionalValue1": "value b", "optionalValue2": null} Please take if for a spin and let me know how it works out. |
We planned to migrate to Graphql Codegen from Artemis, a discontinued project to using GraphQL options.
For query/mutations variables, GraphQL Codegen will remove all fields with
NULL
value during processing, this introduce risks and workload for our backend engineers to migrate while maintaining the behaviour for older releases and our website. Therefore, We would like to see thatincludeIfNullOnInput
build options is available again.Thanks you for your consideration.
The text was updated successfully, but these errors were encountered: