@@ -12,152 +12,171 @@ namespace HotChocolate.Fusion.Extensions;
1212
1313internal static class MutableOutputFieldDefinitionExtensions
1414{
15- public static bool ExistsInSchema ( this MutableOutputFieldDefinition field , string schemaName )
15+ extension ( MutableOutputFieldDefinition field )
1616 {
17- return field . Directives . AsEnumerable ( ) . Any (
18- d =>
19- d . Name == DirectiveNames . FusionField
20- && ( string ) d . Arguments [ ArgumentNames . Schema ] . Value ! == schemaName ) ;
21- }
17+ public void ApplyLookupDirective ( )
18+ {
19+ var lookupDirectiveExists =
20+ field . Directives . AsEnumerable ( ) . Any ( d => d . Name == DirectiveNames . Lookup ) ;
2221
23- public static string ? GetFusionFieldProvides (
24- this MutableOutputFieldDefinition field ,
25- string schemaName )
26- {
27- var fusionFieldDirective =
28- field . Directives . AsEnumerable ( ) . FirstOrDefault (
22+ if ( ! lookupDirectiveExists )
23+ {
24+ field . Directives . Add ( new Directive ( FusionBuiltIns . SourceSchemaDirectives [ DirectiveNames . Lookup ] ) ) ;
25+ }
26+ }
27+
28+ public void ApplyShareableDirective ( )
29+ {
30+ var shareableDirectiveExists =
31+ field . Directives . AsEnumerable ( ) . Any ( d => d . Name == DirectiveNames . Shareable ) ;
32+
33+ if ( ! shareableDirectiveExists )
34+ {
35+ field . Directives . Add ( new Directive ( FusionBuiltIns . SourceSchemaDirectives [ DirectiveNames . Shareable ] ) ) ;
36+ }
37+ }
38+
39+ public bool ExistsInSchema ( string schemaName )
40+ {
41+ return field . Directives . AsEnumerable ( ) . Any (
2942 d =>
3043 d . Name == DirectiveNames . FusionField
3144 && ( string ) d . Arguments [ ArgumentNames . Schema ] . Value ! == schemaName ) ;
45+ }
3246
33- if ( fusionFieldDirective ? . Arguments . TryGetValue ( ArgumentNames . Provides , out var provides ) == true )
47+ public string ? GetFusionFieldProvides ( string schemaName )
3448 {
35- return ( string ? ) provides . Value ;
36- }
49+ var fusionFieldDirective =
50+ field . Directives . AsEnumerable ( ) . FirstOrDefault (
51+ d =>
52+ d . Name == DirectiveNames . FusionField
53+ && ( string ) d . Arguments [ ArgumentNames . Schema ] . Value ! == schemaName ) ;
3754
38- return null ;
39- }
55+ if ( fusionFieldDirective ? . Arguments . TryGetValue ( ArgumentNames . Provides , out var provides ) == true )
56+ {
57+ return ( string ? ) provides . Value ;
58+ }
4059
41- // productById(id: ID!) -> ["id"].
42- // productByIdAndCategoryId(id: ID!, categoryId: Int) -> ["id", "categoryId"].
43- // personByAddressId(id: ID! @is(field: "address.id")) -> ["address.id"].
44- public static List < string > GetFusionLookupMap ( this MutableOutputFieldDefinition field )
45- {
46- var items = new List < string > ( ) ;
60+ return null ;
61+ }
4762
48- foreach ( var argument in field . Arguments )
63+ public List < string > GetFusionLookupMap ( )
4964 {
50- var @is = argument . GetIsFieldSelectionMap ( ) ;
65+ var items = new List < string > ( ) ;
5166
52- items . Add ( @is ?? argument . Name ) ;
67+ foreach ( var argument in field . Arguments )
68+ {
69+ var @is = argument . GetIsFieldSelectionMap ( ) ;
70+
71+ items . Add ( @is ?? argument . Name ) ;
72+ }
73+
74+ return items ;
5375 }
5476
55- return items ;
56- }
77+ public SelectionSetNode ? GetFusionRequiresRequirements ( string schemaName )
78+ {
79+ var fusionRequiresDirective =
80+ field . Directives
81+ . AsEnumerable ( )
82+ . FirstOrDefault (
83+ d =>
84+ d . Name == DirectiveNames . FusionRequires
85+ && ( string ) d . Arguments [ ArgumentNames . Schema ] . Value ! == schemaName ) ;
86+
87+ if ( fusionRequiresDirective is null )
88+ {
89+ return null ;
90+ }
5791
58- public static SelectionSetNode ? GetFusionRequiresRequirements (
59- this MutableOutputFieldDefinition field ,
60- string schemaName )
61- {
62- var fusionRequiresDirective =
63- field . Directives
64- . AsEnumerable ( )
65- . FirstOrDefault (
66- d =>
67- d . Name == DirectiveNames . FusionRequires
68- && ( string ) d . Arguments [ ArgumentNames . Schema ] . Value ! == schemaName ) ;
92+ var requirements = ( string ) fusionRequiresDirective . Arguments [ ArgumentNames . Requirements ] . Value ! ;
6993
70- if ( fusionRequiresDirective is null )
94+ return ParseSelectionSet ( $ "{{ { requirements } }}") ;
95+ }
96+
97+ /// <summary>
98+ /// Rewrites the provided value selections into a selection set string that can be used in a key
99+ /// directive.
100+ /// <example>["a", "b.c"] -> "a b { c }"</example>
101+ /// </summary>
102+ public string GetKeyFields ( List < IValueSelectionNode > valueSelections ,
103+ MutableSchemaDefinition schema )
71104 {
72- return null ;
105+ var valueSelectionToSelectionSetRewriter =
106+ new ValueSelectionToSelectionSetRewriter ( schema , ignoreMissingTypeSystemMembers : true ) ;
107+ var fieldType = field . Type . AsTypeDefinition ( ) ;
108+ var selectionSets = valueSelections
109+ . Select ( s => valueSelectionToSelectionSetRewriter . Rewrite ( s , fieldType ) )
110+ . ToImmutableArray ( ) ;
111+ var mergedSelectionSet = selectionSets . Length == 1
112+ ? selectionSets [ 0 ]
113+ : new MergeSelectionSetRewriter ( schema ) . Merge ( selectionSets , fieldType ) ;
114+
115+ return mergedSelectionSet . ToString ( indented : false ) . AsSpan ( ) [ 2 ..^ 2 ] . ToString ( ) ;
73116 }
74117
75- var requirements = ( string ) fusionRequiresDirective . Arguments [ ArgumentNames . Requirements ] . Value ! ;
118+ public string ? GetOverrideFrom ( )
119+ {
120+ var overrideDirective =
121+ field . Directives . AsEnumerable ( ) . SingleOrDefault ( d => d . Name == DirectiveNames . Override ) ;
76122
77- return ParseSelectionSet ( $ "{{ { requirements } }}" ) ;
78- }
123+ return ( string ? ) overrideDirective ? . Arguments [ ArgumentNames . From ] . Value ;
124+ }
79125
80- /// <summary>
81- /// Rewrites the provided value selections into a selection set string that can be used in a key
82- /// directive.
83- /// <example>["a", "b.c"] -> "a b { c }"</example>
84- /// </summary>
85- public static string GetKeyFields (
86- this MutableOutputFieldDefinition field ,
87- List < IValueSelectionNode > valueSelections ,
88- MutableSchemaDefinition schema )
89- {
90- var valueSelectionToSelectionSetRewriter =
91- new ValueSelectionToSelectionSetRewriter ( schema , ignoreMissingTypeSystemMembers : true ) ;
92- var fieldType = field . Type . AsTypeDefinition ( ) ;
93- var selectionSets = valueSelections
94- . Select ( s => valueSelectionToSelectionSetRewriter . Rewrite ( s , fieldType ) )
95- . ToImmutableArray ( ) ;
96- var mergedSelectionSet = selectionSets . Length == 1
97- ? selectionSets [ 0 ]
98- : new MergeSelectionSetRewriter ( schema ) . Merge ( selectionSets , fieldType ) ;
99-
100- return mergedSelectionSet . ToString ( indented : false ) . AsSpan ( ) [ 2 ..^ 2 ] . ToString ( ) ;
101- }
126+ /// <summary>
127+ /// Gets all combinations of value selections after splitting choice nodes.
128+ /// <example>["a", "{ b } | { c }"] -> [["a", "b"], ["a", "c"]]</example>
129+ /// </summary>
130+ public List < List < IValueSelectionNode > > GetValueSelectionGroups ( )
131+ {
132+ var lookupMap = field . GetFusionLookupMap ( ) ;
133+ var valueSelections = lookupMap . Select ( a => new FieldSelectionMapParser ( a ) . Parse ( ) ) ;
102134
103- public static string ? GetOverrideFrom ( this MutableOutputFieldDefinition field )
104- {
105- var overrideDirective =
106- field . Directives . AsEnumerable ( ) . SingleOrDefault ( d => d . Name == DirectiveNames . Override ) ;
135+ var valueSelectionGroups = valueSelections . Select ( v =>
136+ {
137+ List < IValueSelectionNode > items = [ ] ;
107138
108- return ( string ? ) overrideDirective ? . Arguments [ ArgumentNames . From ] . Value ;
109- }
139+ if ( v is ChoiceValueSelectionNode choiceValueSelectionNode )
140+ {
141+ items . AddRange ( choiceValueSelectionNode . Branches . ToArray ( ) ) ;
142+ }
143+ else
144+ {
145+ items . Add ( v ) ;
146+ }
110147
111- /// <summary>
112- /// Gets all combinations of value selections after splitting choice nodes.
113- /// <example>["a", "{ b } | { c }"] -> [["a", "b"], ["a", "c"]]</example>
114- /// </summary>
115- public static List < List < IValueSelectionNode > > GetValueSelectionGroups (
116- this MutableOutputFieldDefinition field )
117- {
118- var lookupMap = field . GetFusionLookupMap ( ) ;
119- var valueSelections = lookupMap . Select ( a => new FieldSelectionMapParser ( a ) . Parse ( ) ) ;
148+ return items . ToArray ( ) ;
149+ } ) ;
150+
151+ return GetAllCombinations ( valueSelectionGroups . ToArray ( ) ) ;
152+ }
120153
121- var valueSelectionGroups = valueSelections . Select ( v =>
154+ public bool IsPartial ( string schemaName )
122155 {
123- List < IValueSelectionNode > items = [ ] ;
156+ var fusionFieldDirective =
157+ field . Directives . AsEnumerable ( ) . FirstOrDefault (
158+ d =>
159+ d . Name == DirectiveNames . FusionField
160+ && ( string ) d . Arguments [ ArgumentNames . Schema ] . Value ! == schemaName ) ;
124161
125- if ( v is ChoiceValueSelectionNode choiceValueSelectionNode )
162+ if ( fusionFieldDirective is null )
126163 {
127- items . AddRange ( choiceValueSelectionNode . Branches . ToArray ( ) ) ;
164+ return false ;
128165 }
129- else
166+
167+ if ( fusionFieldDirective . Arguments . TryGetValue ( ArgumentNames . Partial , out var partial ) )
130168 {
131- items . Add ( v ) ;
169+ return ( bool ) partial . Value ! ;
132170 }
133171
134- return items . ToArray ( ) ;
135- } ) ;
136-
137- return GetAllCombinations ( valueSelectionGroups . ToArray ( ) ) ;
138- }
139-
140- public static bool IsPartial ( this MutableOutputFieldDefinition field , string schemaName )
141- {
142- var fusionFieldDirective =
143- field . Directives . AsEnumerable ( ) . FirstOrDefault (
144- d =>
145- d . Name == DirectiveNames . FusionField
146- && ( string ) d . Arguments [ ArgumentNames . Schema ] . Value ! == schemaName ) ;
147-
148- if ( fusionFieldDirective is null )
149- {
150172 return false ;
151173 }
152-
153- if ( fusionFieldDirective . Arguments . TryGetValue ( ArgumentNames . Partial , out var partial ) )
154- {
155- return ( bool ) partial . Value ! ;
156- }
157-
158- return false ;
159174 }
160175
176+ // productById(id: ID!) -> ["id"].
177+ // productByIdAndCategoryId(id: ID!, categoryId: Int) -> ["id", "categoryId"].
178+ // personByAddressId(id: ID! @is(field: "address.id")) -> ["address.id"].
179+
161180 private static List < List < T > > GetAllCombinations < T > ( params T [ ] [ ] arrays )
162181 {
163182 if ( arrays . Length == 0 )
0 commit comments