-
Notifications
You must be signed in to change notification settings - Fork 1
Introduces MakeFieldsNullableTypeInterceptor to prevent null propagation #175
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,56 @@ | ||||||||||||||||
| using HotChocolate.Configuration; | ||||||||||||||||
| using HotChocolate.Types.Descriptors; | ||||||||||||||||
| using HotChocolate.Types.Descriptors.Configurations; | ||||||||||||||||
|
Check failure on line 3 in src/Simplic.OxS.Server/GraphQL/MakeFieldsNullableTypeInterceptor.cs
|
||||||||||||||||
|
|
||||||||||||||||
| namespace Simplic.OxS.Server.GraphQL | ||||||||||||||||
| { | ||||||||||||||||
| /// <summary> | ||||||||||||||||
| /// HotChocolate type interceptor that rewrites every output field of every | ||||||||||||||||
| /// user-defined object type so its outermost type becomes nullable. | ||||||||||||||||
| /// <para> | ||||||||||||||||
| /// Purpose: tolerate items that are missing values for fields the schema | ||||||||||||||||
| /// would otherwise mark as <c>NonNull</c>. Without this interceptor, a | ||||||||||||||||
| /// resolver returning <c>null</c> for a <c>!</c>-field causes the parent | ||||||||||||||||
| /// selection-set to be replaced by <c>null</c> (per GraphQL spec). | ||||||||||||||||
| /// </para> | ||||||||||||||||
| /// <para> | ||||||||||||||||
| /// HotChocolate built-in types (introspection, paging connections, etc.) | ||||||||||||||||
| /// are skipped because clients depend on their non-null guarantees. | ||||||||||||||||
| /// </para> | ||||||||||||||||
| /// </summary> | ||||||||||||||||
| internal sealed class MakeFieldsNullableTypeInterceptor : TypeInterceptor | ||||||||||||||||
| { | ||||||||||||||||
| public override void OnBeforeCompleteName( | ||||||||||||||||
| ITypeCompletionContext completionContext, | ||||||||||||||||
| TypeSystemConfiguration configuration) | ||||||||||||||||
|
Check failure on line 25 in src/Simplic.OxS.Server/GraphQL/MakeFieldsNullableTypeInterceptor.cs
|
||||||||||||||||
| { | ||||||||||||||||
| if (completionContext.IsIntrospectionType) | ||||||||||||||||
| return; | ||||||||||||||||
|
|
||||||||||||||||
| if (configuration is not ObjectTypeConfiguration objectConfig) | ||||||||||||||||
| return; | ||||||||||||||||
|
|
||||||||||||||||
| // Skip HotChocolate's own types (Connection, Edge, PageInfo, ...). | ||||||||||||||||
| var runtimeType = objectConfig.RuntimeType; | ||||||||||||||||
| if (runtimeType?.Namespace is { } ns && | ||||||||||||||||
| ns.StartsWith("HotChocolate", System.StringComparison.Ordinal)) | ||||||||||||||||
| { | ||||||||||||||||
|
Comment on lines
+35
to
+37
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tighten the namespace guard to avoid skipping user types. Line 36 uses Suggested fix- if (runtimeType?.Namespace is { } ns &&
- ns.StartsWith("HotChocolate", System.StringComparison.Ordinal))
+ if (runtimeType?.Namespace is { } ns &&
+ (ns.Equals("HotChocolate", System.StringComparison.Ordinal) ||
+ ns.StartsWith("HotChocolate.", System.StringComparison.Ordinal)))
{
return;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||
| return; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| foreach (var field in objectConfig.Fields) | ||||||||||||||||
| { | ||||||||||||||||
| if (field.IsIntrospectionField) | ||||||||||||||||
| continue; | ||||||||||||||||
|
|
||||||||||||||||
| if (field.Type is not ExtendedTypeReference extRef) | ||||||||||||||||
| continue; | ||||||||||||||||
|
|
||||||||||||||||
| var nullableType = completionContext.TypeInspector | ||||||||||||||||
| .ChangeNullability(extRef.Type, true); | ||||||||||||||||
|
|
||||||||||||||||
| field.Type = extRef.WithType(nullableType); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: simplic/simplic-oxs
Length of output: 1195
🏁 Script executed:
cat -n src/Simplic.OxS.Server/Extensions/GraphQLExtension.cs | head -50Repository: simplic/simplic-oxs
Length of output: 2607
Mark the optional builder callback as nullable.
Line 24 assigns
nullto a non-nullable delegate type. UseAction<IRequestExecutorBuilder>?to align with the enabled nullable reference type context.Suggested fix
📝 Committable suggestion
🤖 Prompt for AI Agents